{"record":{"id":"41b9d616db20cf2f","repo":"strapi/strapi","slug":"invalid-key-key","errorCode":null,"errorMessage":"Invalid key ${key}","messagePattern":"Invalid key (.+?)","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"packages/core/admin/server/src/services/permission/permissions-manager/validate.ts","lineNumber":39,"sourceCode":"  contentTypes;\nconst {\n  ID_ATTRIBUTE,\n  DOC_ID_ATTRIBUTE,\n  CREATED_AT_ATTRIBUTE,\n  UPDATED_AT_ATTRIBUTE,\n  PUBLISHED_AT_ATTRIBUTE,\n  CREATED_BY_ATTRIBUTE,\n  UPDATED_BY_ATTRIBUTE,\n} = constants;\n\nconst COMPONENT_FIELDS = ['__component'];\n\nconst STATIC_FIELDS = [ID_ATTRIBUTE, DOC_ID_ATTRIBUTE];\n\nconst throwInvalidKey = ({ key, path }: { key: string; path?: string | null }) => {\n  const msg = path && path !== key ? `Invalid key ${key} at ${path}` : `Invalid key ${key}`;\n\n  throw new ValidationError(msg);\n};\n\nexport default ({ action, ability, model }: any) => {\n  const schema = strapi.getModel(model);\n\n  // Create request-scoped model cache to avoid redundant getModel() calls\n  const modelCache = createModelCache(strapi.getModel.bind(strapi));\n\n  const ctx = {\n    schema,\n    getModel: modelCache.getModel,\n  };\n\n  const createValidateQuery = (options = {} as any) => {\n    const { fields } = options;\n\n    // TODO: validate relations to admin users in all validators\n    const permittedFields = fields.shouldIncludeAll ? null : getQueryFields(fields.permitted);","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/strapi/strapi/blob/4a4101264d7098754df36e85fa629fd2f2349d8c/packages/core/admin/server/src/services/permission/permissions-manager/validate.ts#L21-L57","documentation":"Thrown by the same throwInvalidKey helper as error 80, but without a nested path suffix. The plain 'Invalid key ${key}' message is emitted when the violating key is at the top level of the query (path equals key or is absent), so no location qualifier is appended. It represents the same RBAC/schema validation failure class: a visitor detected a disallowed field during filters/sort/populate/fields traversal.","triggerScenarios":"A top-level query key violates the permission visitors: a disallowed field name in fields:[...], a top-level filter on a non-permitted attribute, a hidden attribute, a password field, or a disallowed admin::user field. Distinguished from error 80 only by the absence of a distinct nested path.","commonSituations":"Calling content-manager endpoints with a fields array or populate object that references a field the current role cannot read. A plugin auto-injecting query params that breach RBAC. Migrating from CE to EE where field-level permissions tighten enforcement.","solutions":["Remove the offending key named in the message from the query.","Grant the user's role read access to that field via the admin RBAC settings.","If the field is hidden or private, switch to an allowed field or unhide it in the content-type schema.","Sanitize client-supplied query parameters against the content-type's writable/visible attribute list before forwarding."],"exampleFix":"// before\nstrapi.documents('api::article.article').findMany({\n  fields: ['title', 'internalNotes'], // internalNotes not permitted\n});\n// after\nstrapi.documents('api::article.article').findMany({\n  fields: ['title'],\n});","handlingStrategy":"validation","validationCode":"const visible = strapi.contentTypes[uid] ? Object.entries(strapi.contentTypes[uid].attributes).filter(([,a])=>!a.hidden).map(([k])=>k) : [];\nconst safeFields = (query.fields || []).filter((f) => visible.includes(f));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate requested fields against the content-type's visible attributes.","Avoid requesting hidden or password fields.","Run RBAC field-permission checks in your API gateway/middleware."],"tags":["rbac","validation","permissions","query","content-manager"],"backgroundTag":null,"analyzedSha":"4a4101264d7098754df36e85fa629fd2f2349d8c","analyzedAt":"2026-08-12T12:47:50.760Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}