{"record":{"id":"019b2d64ef9b22f5","repo":"payloadcms/payload","slug":"the-folder-data-name-originaldoc-name-mus","errorCode":null,"errorMessage":"The folder \"${data?.name || originalDoc.name}\" must have folder-type set since its parent folder ${parentFolder?.name ? `\"${parentFolder?.name}\" ` : ''}has a folder-type set.","messagePattern":"The folder \"(.+?)\" must have folder-type set since its parent folder (.+?)\" ` : ''\\}has a folder-type set\\.","errorType":"http","errorClass":"APIError","httpStatus":400,"severity":"error","filePath":"packages/payload/src/hierarchy/hooks/ensureSafeCollectionsChange.ts","lineNumber":139,"sourceCode":"            select: {\n              name: true,\n              [typeFieldName]: true,\n            },\n            user: req.user,\n          })\n        } catch (_) {\n          // parent folder does not exist\n        }\n      }\n\n      const parentTypeValue = parentFolder?.[typeFieldName]\n      if (\n        parentFolder &&\n        parentTypeValue &&\n        Array.isArray(parentTypeValue) &&\n        parentTypeValue.length > 0\n      ) {\n        throw new APIError(\n          `The folder \"${data?.name || originalDoc.name}\" must have folder-type set since its parent folder ${parentFolder?.name ? `\"${parentFolder?.name}\" ` : ''}has a folder-type set.`,\n          400,\n        )\n      }\n    }\n\n    return data\n  }\n","sourceCodeStart":121,"sourceCodeEnd":148,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/hierarchy/hooks/ensureSafeCollectionsChange.ts#L121-L148","documentation":"Thrown by ensureSafeCollectionsChange when a folder's hierarchyType is being cleared (set to null/empty) while its parent folder still has a restricted type list. A child cannot be a catch-all when its parent is typed. HTTP 400 APIError.","triggerScenarios":"Setting data.hierarchyType to null or [] on a folder whose parent (resolved via data.folder/originalDoc.folder) has a non-empty hierarchyType array.","commonSituations":"User clears the folder-type field without realising the parent constrains it; moving an untyped folder under a typed parent via the UI.","solutions":["Keep a non-empty hierarchyType that is a subset of the parent's allowed types.","Clear or widen the parent's type first, then clear the child's.","Move the folder to an untyped parent before clearing its type.","In the UI, disable clearing the type when the parent is typed."],"exampleFix":"// before\nawait payload.update({ collection: 'payload-folders', id: childId, data: { hierarchyType: null } })\n\n// after — inherit a valid subset of the parent's types\nconst parent = await payload.findByID({ collection: 'payload-folders', id: parentId })\nawait payload.update({\n  collection: 'payload-folders',\n  id: childId,\n  data: { hierarchyType: parent.hierarchyType },\n})","handlingStrategy":"validation","validationCode":"const parent = await payload.findByID({\n  collection: foldersSlug,\n  id: parentId,\n  overrideAccess: true,\n})\nif (Array.isArray(parent?.[typeFieldName]) && parent[typeFieldName].length > 0) {\n  throw new Error('parent is typed; child must keep a type')\n}","typeGuard":"function parentIsTyped(parent: any, typeFieldName: string): boolean {\n  return Array.isArray(parent?.[typeFieldName]) && parent[typeFieldName].length > 0\n}","tryCatchPattern":"try {\n  await payload.update({ collection: foldersSlug, id: childId, data })\n} catch (err) {\n  if (err instanceof APIError && err.statusCode === 400 && /folder-type set/.test(err.message)) {\n    return { error: err.message }\n  }\n  throw err\n}","preventionTips":["Inherit a subset of the parent's types rather than clearing them.","Widen or clear the parent's type first if a catch-all child is required."],"tags":["hierarchy","folders","validation","before-validate","api-error-400"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}