#Updating Array Field Hangs in CollectionAfterOperationHook

1 messages · Page 1 of 1 (latest)

clear hullBOT
#

Hey!

I'm having issues programatically updating an array field containing objects.
I have a CollectionAfterOperationHook that runs this code on a 'create' operation:

const { user, payload } = req
console.log('Starting')
await payload.update({
  collection: 'users',
  id: user.id,
  data: {
    projects: [
      {
        role: 'admin',
        project: projectId,
      },
    ],
  },
})
console.log('resolved')

The user.projects is defined as follows:

{
  name: 'projects',
  type: 'array',
  label: 'Projects',
  fields: [
    {
      name: 'project',
      type: 'relationship',
      relationTo: 'projects',
      required: true,
    },
    {
      name: 'role',
      type: 'select',
      hasMany: false,
      required: true,
      options: [
        {
          label: 'Admin',
          value: 'admin',
        },
        {
          label: 'User',
          value: 'user',
        },
      ],
    },
  ],
}

Whenever the hook is run the request is stuck forever and the resolved log is never printed.
I'm on beta 65 (but had the same issue with beta 60) and I'm using postgres.
Any ideas what is causing this or how to work around it?

mortal sorrelBOT
#

Original message from @analog stump - Moved from #archive_v3-feedback message

slate jackal
#

Have you tried wrapping it in a trycatch to see if there is some sort of error maybe?

analog stump
#

I just did but it looks like nothing is thrown. I also tried with a fresh DB but it didn't help.

slate jackal
#

Can you provide the full hook code?

#

Looks like you just provided the internals

analog stump
#

Sure!

const hook: CollectionAfterOperationHook<'projects'> = async ({
  args, // arguments passed into the operation
  operation, // name of the operation
  req, // full express request
  result, // the result of the operation, before modifications
}) => {
  const { user, payload } = req

  if (!user) {
    return result
  }
  if (operation === 'create' && result.creator === user.id) {
    const projectId = result.id

    console.log('Starting')
    console.log({ projectId })
    try {
      await payload.update({
        collection: 'users',
        id: user.id,
        data: {
          projects: [
            {
              role: 'admin',
              project: projectId,
            },
          ],
        },
      })
    } catch (error) {
      console.error('An error', error)
    }
    console.log('resolved')
  }
  return result
}
slate jackal
#

Hmm, makes me wonder if updating the user's projects is causing a recursive loop.

#

Can you try updating something else to rule that out?

analog stump
#

Of course, I'll try!

slate jackal
#

Maybe changing some other prop on the user

analog stump
#
const hook: CollectionAfterOperationHook<'projects'> = async ({
  args, // arguments passed into the operation
  operation, // name of the operation
  req, // full express request
  result, // the result of the operation, before modifications
}) => {
  const { user, payload } = req

  if (!user) {
    return result
  }
  if (operation === 'create' && result.creator === user.id) {
    const projectId = result.id

    console.log('Starting')
    console.log({ projectId })
    try {
      await payload.update({
        collection: 'users',
        id: user.id,
        data: {
          firstName: 'Test name',
        },
      })
    } catch (error) {
      console.error('error', error)
    }
    console.log('resolved')
  }
  return result
}

Still the same problem 🤔

#

What's weird is that I have an API endpoint on the user collection running the same update code and it works fine.

#

Same happens using afterChange if that helps

analog stump
#

I have another collection, "Agencies" to which the user collection holds the same kind of references (inspired by the multi-tenant example). Updating anything from "Agencies" doesn't work either (same problem). Updating fields of other collections works fine in the hook.

analog stump
#

Hi @slate jackal,
I know it has been a while but I'm taking another look at this and found out that the payload.update resolves as expected if I wrap it in a setTimeout :


const hook: CollectionAfterChangeHook<Project> = async ({
  doc, // full document data
  req, // full express request
  previousDoc, // document data before updating the collection
  operation, // name of the operation ie. 'create', 'update'
}) => {
  const { user, payload } = req

  if (!user) {
    return doc
  }
  if (operation === 'create' && doc.creator === user.id) {
    const projectId = doc.id

    console.log('Starting')
    console.log({ projectId })
    try {
      setTimeout(async () => {
        await payload.update({
          collection: 'users',
          id: user!.id,
          data: {
            projects: [
              {
                role: 'admin',
                project: projectId,
              },
            ],
          },
        })
        console.log('resolved')
      }, 0)
    } catch (error) {
      console.error('An error', error)
    }
  }
  return doc
}

Without the setTimeout the create operation is stuck and resolved is never logged.
Does this give you any idea what could be going on here?

tardy quest
analog stump
#

Thanks for letting me know, definitely sounds like it could be related!

analog stump
#

@tardy quest / @slate jackal: The fix proposed in @tardy quest's thread (#1267772733899407513 message) indeed fixed the problem for me. I just had to pass the req to the update options:

await payload.update({
  req,
  collection: 'users',
  id: user!.id,
  data: {
    projects: [
      {
        role: 'admin',
        project: projectId,
      },
    ],
  },
})

This is the related Issue on Github: https://github.com/payloadcms/payload/issues/7352

I don't quite understand why yet but I'm glad it works.

GitHub

Link to reproduction https://github.com/mcornielje090404/payload-3.0-demo/tree/main Payload Version 3.0.0-beta.67 Node Version 20.13.1 Next.js Version 15.0.0-canary.58 Describe the Bug When attempt...