{"record":{"id":"ee00266145dc5eb2","repo":"makeplane/plane","slug":"missing-required-fields","errorCode":null,"errorMessage":"Missing required fields.","messagePattern":"Missing required fields\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/web/core/store/pages/project-page.ts","lineNumber":31,"sourceCode":"import type { RootStore } from \"@/store/root.store\";\n// services\nimport { ProjectPageService } from \"@/services/page\";\nconst projectPageService = new ProjectPageService();\n// store\nimport { BasePage } from \"./base-page\";\nimport type { TPageInstance } from \"./base-page\";\n\nexport type TProjectPage = TPageInstance;\n\nexport class ProjectPage extends BasePage implements TProjectPage {\n  constructor(store: RootStore, page: TPage) {\n    // required fields for API calls\n    const { workspaceSlug } = store.router;\n    const projectId = page.project_ids?.[0];\n    // initialize base instance\n    super(store, page, {\n      update: async (payload) => {\n        if (!workspaceSlug || !projectId || !page.id) throw new Error(\"Missing required fields.\");\n        return await projectPageService.update(workspaceSlug, projectId, page.id, payload);\n      },\n      updateDescription: async (document) => {\n        if (!workspaceSlug || !projectId || !page.id) throw new Error(\"Missing required fields.\");\n        await projectPageService.updateDescription(workspaceSlug, projectId, page.id, document);\n      },\n      updateAccess: async (payload) => {\n        if (!workspaceSlug || !projectId || !page.id) throw new Error(\"Missing required fields.\");\n        await projectPageService.updateAccess(workspaceSlug, projectId, page.id, payload);\n      },\n      lock: async () => {\n        if (!workspaceSlug || !projectId || !page.id) throw new Error(\"Missing required fields.\");\n        await projectPageService.lock(workspaceSlug, projectId, page.id);\n      },\n      unlock: async () => {\n        if (!workspaceSlug || !projectId || !page.id) throw new Error(\"Missing required fields.\");\n        await projectPageService.unlock(workspaceSlug, projectId, page.id);\n      },","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/makeplane/plane/blob/1c8a60f858d8472aa56e29994ec1c7926da2c6ce/apps/web/core/store/pages/project-page.ts#L13-L49","documentation":"First of eight identical guards in the ProjectPage constructor (apps/web/core/store/pages/project-page.ts). The `update` handler throws 'Missing required fields.' when any of workspaceSlug (from store.router), projectId (page.project_ids[0]), or page.id is absent. These three are required path parameters for every projectPageService call.","triggerScenarios":"Invoking page.update() before router params are populated; constructing a ProjectPage from a TPage that has no project_ids or no id; calling update during route transitions where router.workspaceSlug is briefly undefined.","commonSituations":"Optimistic page mutation fired on mount before route resolution; page record loaded from a partial/socket payload missing project_ids; navigating away mid-edit leaves a stale page instance whose router context is gone.","solutions":["Ensure the page is rendered within a route where workspaceSlug and projectId are resolved before enabling edit actions.","Validate page.project_ids?.[0] and page.id are non-empty when constructing ProjectPage; skip instantiation otherwise.","Gate mutation UI on a computed `canEdit` that checks all three fields.","If the fields can legitimately be absent, lazy-resolve them (await router/scrollToPage) before invoking update."],"exampleFix":"// before\nupdate: async (payload) => {\n  if (!workspaceSlug || !projectId || !page.id) throw new Error(\"Missing required fields.\");\n  return await projectPageService.update(workspaceSlug, projectId, page.id, payload);\n}\n// after: early no-op with a warning instead of a hard throw\nupdate: async (payload) => {\n  if (!workspaceSlug || !projectId || !page.id) {\n    console.warn('ProjectPage.update skipped: missing identifiers');\n    return;\n  }\n  return await projectPageService.update(workspaceSlug, projectId, page.id, payload);\n}","handlingStrategy":"validation","validationCode":"const { workspaceSlug } = store.router;\nconst projectId = page.project_ids?.[0];\nif (!workspaceSlug || !projectId || !page.id) { console.warn('update skipped'); return; }","typeGuard":"const hasPageIdentifiers = (s: {workspaceSlug?: string}, p: {project_ids?: string[]; id?: string}) =>\n  Boolean(s.workspaceSlug && p.project_ids?.[0] && p.id);","tryCatchPattern":"try { await page.update(payload); }\ncatch (e) { if (/Missing required fields/.test(e.message)) showPageNotReady(); else throw e; }","preventionTips":["Only mount page edit UI inside a resolved route context.","Compute a `canEdit` flag from the three identifiers and use it to disable actions.","Refetch the page if project_ids is empty before exposing actions."],"tags":["pages","web","precondition","router-params","validation"],"backgroundTag":null,"analyzedSha":"1c8a60f858d8472aa56e29994ec1c7926da2c6ce","analyzedAt":"2026-08-12T14:44:31.636Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}