# Trigger on doc changes not working

**URL:** <https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317>\
**Category:** Get Help\
**Tags:** automations\
**Created:** [April 13, 2023, 4:38pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317 "2023-04-13T16:38:40Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 13, 2023, 4:38pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/1 "2023-04-13T16:38:40Z")

</div>

Hmmm… I copied my Task’s (working) “Sync Details” Button (including the script, verbatim) as a “Sync Details” Rule (triggered by the “Details” field changing) and tested it by editing the Details field in a Task entity: the Rule shows as having run successfully (under Activity) but the effect didn’t occur (the script should update “Searchable Details" rich text field). So the same script works fine as a Button, but not as Rule: is there something different about the script API for Rules vs Buttons?

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 13, 2023, 4:50pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/2 "2023-04-13T16:50:14Z")

</div>

Sounds unusual. Can you post the script here, together with any useful screen grabs from the activity log.

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 13, 2023, 5:05pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/3 "2023-04-13T17:05:51Z")

</div>

```auto
// Developer reference is at api.fibery.io/#action-buttons

const logging = false
const create_searchable_details = true
const update_collection_fields = true
const create_outcome = false

// Lookup table for mapping typeId to entity Name and corresponding
// Referenced Entity field. Note: this table must be extended
// whenever a new Database is added (if it might be Referenced), or
// modified whenever a Database's Name is updated.

const lookup = {
    'e5f3e990-815a-11ec-adbf-35e3df6ae56f': {
        'name': 'Tag',
        'field': 'Referenced Tags'
    },
    '53c77c70-7cb5-11ec-bdf4-9d8359eb2d89': {
        'name': 'Person',
        'field': 'Referenced People'
    },
    'bdefbc60-7cb6-11ec-bdf4-9d8359eb2d89': {
        'name': 'Product',
        'field': 'Referenced Products'
    },
    'ee89f9a0-7cb4-11ec-bdf4-9d8359eb2d89': {
        'name': 'Organization',
        'field': 'Referenced Organizations'
    },
    '87c49720-7cdc-11ec-bdf4-9d8359eb2d89': {
        'name': 'Trial',
        'field': 'Referenced Trials'
    },
    '54a09420-5dac-11eb-836f-5117371ac1ee': {
        'name': 'Task',
        'field': 'Referenced Tasks'
    },
    '8f95e150-70c7-11ec-b97d-972ab98146c5': {
        'name': 'Epic',
        'field': 'Referenced Epics'
    },
    '848451a0-78e9-11ec-9cbf-ed2f2cff2041': {
        'name': 'Project',
        'field': 'Referenced Projects'
    },
    'ad167630-7014-11ec-9df5-c99d2f84b20b': {
        'name': 'Milestone',
        'field': 'Referenced Milestones'
    },
    'efbd97f0-5dac-11eb-836f-5117371ac1ee': {
        'name': 'Goal',
        'field': 'Referenced Goals'
    },
    '1ad6b940-7cb4-11ec-bdf4-9d8359eb2d89': {
        'name': 'Note',
        'field': 'Referenced Notes'
    }
}

// Create and initialize a field_names list with the names of the
// collection fields listing the corresponding referenced entities.
const field_names = []
for (var key in lookup) {
    field_names.push(lookup[key]['field'])
}

// Recursively traverse the (rich text) document object, storing all
// entity references and then replacing them in-place with the names
// of the referenced entities.
async function traverse1(fibery, parent) {
    let is_entity = false
    for (let child_key in parent) {
        const child = parent[child_key]
        if (child_key == "type" && child == "entity") is_entity = true
        if (typeof child === "object") {
            if (is_entity && child_key == "attrs") {
                const id = child['id']
                const type_id = child['typeId']
                if (logging) console.log("FOUND ENTITY: id: " + id + " type_id: " + type_id)
                const inferred_type = lookup[type_id]['name']
                const reference = await fibery.getEntityById(inferred_type, id, ['Name'])
                found_refs[inferred_type].push(reference)
                return reference['Name']
            } else {
                const name = await traverse1(fibery, child)
                if (name !== null) parent[child_key] = { 'type': 'text', 'text': name }
            }
        }
    }
    return null
}

async function traverse(fibery, found_refs, parent) {
    let is_entity = false
    for (let child_key in parent) {
        const child = parent[child_key]
        if (child_key == "type" && child == "entity") is_entity = true
        if (typeof child === "object") {
            if (is_entity && child_key == "attrs") {
                const id = child['id']
                const type_id = child['typeId']
                if (logging) console.log("FOUND ENTITY: id: " + id + " type_id: " + type_id)
                const inferred_type = lookup[type_id]['name']
                const reference = await fibery.getEntityById(inferred_type, id, ['Name'])
                found_refs[inferred_type].push(reference)
                return reference['Name']
            } else {
                const name = await traverse(fibery, found_refs, child)
                if (name !== null) parent[child_key] = { 'type': 'text', 'text': name }
            }
        }
    }
    return null
}

// Remove all entity references in list from designated collection.
async function emptyReferenceList(fibery, entity, ref_type, refs) {
    for (const ref of refs) {
        if (logging) console.log("REMOVE " + ref_type + " REF: " + ref.Id)
        await fibery.removeCollectionItem(entity.type, entity.id, ref_type, ref.Id)
    }
}

// Add all entity references in list to designated collection.
async function setReferenceList(fibery, entity, ref_type, refs) {
    for (const ref of refs) {
        if (logging) console.log("ADD " + ref_type + " REF: " + ref.Id)
        await fibery.addCollectionItem(entity.type, entity.id, ref_type, ref.Id)
    }
}

// Fibery API is used to retrieve and update entities
const fibery = context.getService('fibery')

// affected entities are stored in args.currentEntities;
// to support batch actions they always come in an array
for (const entity of args.currentEntities) {
    // an entity contains all fields apart from collections;
    // to access a field refer to it by its UI name

    // Note: we could also get a restricted copy of the entity contain only
    // the Details field (+ Id) like this (but not necessary):
    // const x = await fibery.getEntityById(entity.type, entity.id, ['Details'])
    // That is also the ONLY way to get collection fields, eg:
    // const entity2 = await fibery.getEntityById(entity.type, entity.id, ['Tags', 'Epic Tags'])
    // const tags = entity2['Tags']
    // const epic_tags = entity2['Epic Tags']
    // We could also use that method to get the *incoming* references (entities
    // which have referenced this entity):
    // const entity2 = await fibery.getEntityById(entity.type, entity.id, ['References']);
    // const references = entity2['References']
    // although unfortunately there's no way to get a list of entities that this
    // entity references: for that we have to crawl through the rich text fields, as below.

    const details = entity['Details']
    const searchable_details = entity['Searchable Details']

    if (logging) {
        console.log("Entity:")
        console.log(entity)
        console.log("Details:")
        console.log(details)
    }

    const document = await fibery.getDocumentContent(details['secret'], "json")
    const entity2 = await fibery.getEntityById(entity.type, entity.id, field_names)

    if (logging) {
        console.log("Document:")
        console.log(document)
        console.log("Entity + collection fields:")
        console.log(entity2)
    }

    if (update_collection_fields) {
        // Remove existing references (in any case, since if there's
        // no rich text then all collection fields should be empty).
        for (var key in lookup) {
            const field_name = lookup[key]['field']
            await emptyReferenceList(fibery, entity, field_name, entity2[field_name])
        }
    }

    if (document != null) {
        // Create and initialize a found_refs dictionary with the names of
        // the referenced entities.
        const found_refs = {}
        for (var key in lookup) {
            found_refs[lookup[key]['name']] = []
        }

        // Store all entity references found in document, replacing
        // them in-place with the names of the referenced entities.
        await traverse(fibery, found_refs, document)

        if (logging) {
            console.log("Stripped document:")
            console.log(document)
        }

        if (create_searchable_details) {
            // Update the search details field with the stripped text.
            await fibery.setDocumentContent(searchable_details['secret'], document, "json")
        }

        if (create_outcome) {
            // Update the (non-rich text) outcome field with the
            // stripped text (this will strip all remaining structure,
            // but the reference names will survive because they've
            // already been replaced with text).
            await fibery.updateEntity(entity.type, entity.id, { 'Outcome': document })
        }

        if (update_collection_fields) {
            // Update all the collection fields with the stored lists of
            // referenced entities.
            for (var key in lookup) {
                const name = lookup[key]['name']
                const field_name = lookup[key]['field']
                await setReferenceList(fibery, entity, field_name, found_refs[name])
            }
        }
    } else if (create_searchable_details) {
        // There's no rich text, so the search text field must be empty.
        await fibery.setDocumentContent(searchable_details['secret'], "", "md")
    }
}

```

1 action was executed Apr 13, 2023 09:32 Completed  
Script executed Completed

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 13, 2023, 5:17pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/4 "2023-04-13T17:17:21Z")

</div>

I can see that there are console.log entries in the script. Are you getting these messages in the activity log for the automation (or can you turn on logging to see what you get)?

And maybe a stupid question: is it definitely the same script being run when it works with a button as it is when it runs triggered by a rich text field change?

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 13, 2023, 5:29pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/5 "2023-04-13T17:29:24Z")

</div>

Actually no I don’t see any output in the console, even when I run the script via the button. Yes it’s the same exact script: copied & pasted from button to rule just now.

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 13, 2023, 5:33pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/6 "2023-04-13T17:33:01Z")

</div>

I’m not a sw engineer, but these lines seem a bit funny to me…

> [@masp](#):
>
> ```auto
> if (child_key == "type" && child == "entity") is_entity = true
> if (typeof child === "object") {
> if (is_entity && child_key == "attrs") {
> 
> ```

Given that `is_entity` is only true when `child_key == "type"` then I can’t see how `is_entity && child_key == "attrs"` can ever be true.  
Or am I missing something?

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 13, 2023, 5:58pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/7 "2023-04-13T17:58:06Z")

</div>

Seems fair: this is pretty old code now so I’ll have to revisit it at some point: but it does work, as a button: just not as a rule.

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 13, 2023, 7:01pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/8 "2023-04-13T19:01:36Z")

</div>

I’d suggest turning on the logging and seeing what you can deduce from the console logging.

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 2:37pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/9 "2023-04-14T14:37:12Z")

</div>

I’m not seeing any logging output: it’s as if the script isn’t getting run. BTW this script/automation is a long-standing workaround for the fact that entity names aren’t included in the search index: is a fix for that on the roadmap? (eg. if I include “created a new [EC2] instance” (where [EC2] is a reference to an entity named “EC2”) and then I search for the string “EC2” that string will not appear in the results).

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 14, 2023, 2:47pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/10 "2023-04-14T14:47:00Z")

</div>

> [@masp](#):
>
> I’m not seeing any logging output

You will see console output only if run as a button. Otherwise, the log output will appear in the activity tab of the automation rule, after it has run.

> [@masp](#):
>
> entity names aren’t included in the search index

We have a feature for #mentioned items to be indexed in search, but no ETA I’m afraid.

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 3:27pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/11 "2023-04-14T15:27:40Z")

</div>

How odd: I’m not seeing any activity today: even though I’ve tried editing the ‘Details’ field in a task a couple of times.

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 3:28pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/12 "2023-04-14T15:28:45Z")

</div>

Do you have access to my account btw? If so do feel free to explore: it’s the “Sync Details” rule (of Task) that’s not working: which is a verbatim copy of the “Sync Details” button (of Task) that works.

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 14, 2023, 3:42pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/13 "2023-04-14T15:42:20Z")

</div>

We don’t get access to users’ workspaces unless explicitly granted. If you wanted me to dig into it, you can invite me (ideally as an admin): [chris@fibery.io](mailto:chris@fibery.io)

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 14, 2023, 3:44pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/14 "2023-04-14T15:44:01Z")

</div>

BTW, I have split out into a new topic thread to avoid polluting the original

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 5:23pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/15 "2023-04-14T17:23:52Z")

</div>

You’ve already got access actually (admin): please go ahead and thanks!!

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [April 14, 2023, 5:46pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/16 "2023-04-14T17:46:55Z")

</div>

OK great. I’ll message you on chat to save this discourse topic becoming a massive thread!

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 6:15pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/17 "2023-04-14T18:15:29Z")

</div>

Good grief: looks like it’s working after all! The Searchable Details field just updated after only 1-2 seconds. I swear that wasn’t happening before! Did you change something? Or maybe I just wasn’t waiting long enough? Oh well: if it’s consistently working then that’s great news!!

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 6:17pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/18 "2023-04-14T18:17:33Z")

</div>

BTW Is there an easy way for me to run my “Sync Details” script (it’s the same script in both the button and the rule) as a one-off, applied to every Task? (So as to make sure that Searchable Details is up-to-date with Details on every Task, since I’ve certainly not always remembered to press the “Sync Details” button after every change in the past.)

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 6:25pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/19 "2023-04-14T18:25:52Z")

</div>

I thought about it and figured maybe I could rewrite the script with an outer loop over Tasks and then attach it as an automation to a “database” that has all Tasks related to it, and run it there via a button? But it there a simpler way?

---

<div class="post-metadata">

**Author:** ![masp](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@masp](https://community.fibery.io/u/masp)\
**Post date:** [April 14, 2023, 6:27pm UTC](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317/20 "2023-04-14T18:27:32Z")

</div>

Or (better): can I create an automation (button) on a database that has a Tasks relation (all Tasks) but then that automation TRIGGERS the Sync Details Button (or Rule) on each Task? (So the script for that (outer) automation could just a loop over the Task relations and the synchronization code could remain in the Task automation(s).)

[Next page](https://community.fibery.io/t/trigger-on-doc-changes-not-working/4317.md?page=2)
