{"record":{"id":"e1bebe1f570201f4","repo":"paperclipai/paperclip","slug":"project-belongs-to-another-company-or-does-not-exi","errorCode":null,"errorMessage":"Project belongs to another company or does not exist: ${projectId}","messagePattern":"Project belongs to another company or does not exist: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/plugin-llm-wiki/src/wiki/core.ts","lineNumber":1007,"sourceCode":"  });\n  if (!policy.allowed) throw new Error(policy.message);\n  if (input.profile.enabled && input.profile.sourceScopes.length === 0) {\n    throw new Error(\"Paperclip ingestion profile must include at least one source scope before it can be enabled.\");\n  }\n  if (input.profile.sourceScopes.length > MAX_PAPERCLIP_INGESTION_PROFILE_SOURCE_COUNT) {\n    throw new Error(`Paperclip ingestion profile sources exceed the hard cap of ${MAX_PAPERCLIP_INGESTION_PROFILE_SOURCE_COUNT}.`);\n  }\n  for (const scope of input.profile.sourceScopes) {\n    if (scope.kind === \"company_all\" && input.space.slug !== DEFAULT_SPACE_SLUG) {\n      throw new Error(\"Everything in the company is only available on the default wiki space.\");\n    }\n    if (scope.kind === \"selected_projects\") {\n      if (scope.projectIds.length > MAX_PAPERCLIP_PROFILE_SELECTED_PROJECTS) {\n        throw new Error(`selected_projects exceeds the hard cap of ${MAX_PAPERCLIP_PROFILE_SELECTED_PROJECTS}.`);\n      }\n      for (const projectId of scope.projectIds) {\n        const project = await ctx.projects.get(projectId, input.companyId);\n        if (!project) throw new Error(`Project belongs to another company or does not exist: ${projectId}`);\n      }\n    }\n    if (scope.kind === \"root_issues\") {\n      if (scope.issueIds.length > MAX_PAPERCLIP_PROFILE_ROOT_ISSUES) {\n        throw new Error(`root_issues exceeds the hard cap of ${MAX_PAPERCLIP_PROFILE_ROOT_ISSUES}.`);\n      }\n      for (const issueId of scope.issueIds) {\n        const issue = await ctx.issues.get(issueId, input.companyId);\n        if (!issue) throw new Error(`Issue belongs to another company or does not exist: ${issueId}`);\n      }\n    }\n  }\n}\n\nexport async function updatePaperclipIngestionProfile(ctx: PluginContext, input: {\n  companyId: string;\n  wikiId?: string | null;\n  spaceSlug?: string | null;","sourceCodeStart":989,"sourceCodeEnd":1025,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/plugin-llm-wiki/src/wiki/core.ts#L989-L1025","documentation":"Thrown during profile validation when ctx.projects.get(projectId, companyId) returns nullish for a project id listed in a 'selected_projects' scope. The projects.get helper is company-scoped, so a null result means the id is unknown or belongs to a different company. This guards ingestion from binding to projects outside the company boundary.","triggerScenarios":"Submitting a 'selected_projects' scope whose projectIds includes an id that was deleted, mis-typed, copied from another company, or pending creation. The lookup happens inside validatePaperclipIngestionProfile, reached via updatePaperclipIngestionProfile.","commonSituations":"Stale project id cached in a UI form after the project was archived/deleted; cross-company copy-paste of ids; test fixtures referencing a project from a different tenant; race between project creation and profile save.","solutions":["Call listPaperclipIngestionCandidates first and restrict the picker to ids it returns for the current company.","Strip project ids that no longer exist before submitting, or surface them to the user for re-selection.","Verify the companyId passed into the profile update matches the company that owns every projectId.","If a project was just created, wait for it to be readable before adding it to the scope."],"exampleFix":"// before\nprofile.sourceScopes = [{ kind: \"selected_projects\", projectIds: rawProjectIds }];\n\n// after\nconst candidates = await listPaperclipIngestionCandidates(ctx, { companyId, wikiId });\nconst valid = new Set(candidates.projects.map((p) => p.id));\nprofile.sourceScopes = [{\n  kind: \"selected_projects\",\n  projectIds: rawProjectIds.filter((id) => valid.has(id)),\n}];","handlingStrategy":"validation","validationCode":"async function filterExistingProjects(ctx, companyId, projectIds) {\n  const candidates = await listPaperclipIngestionCandidates(ctx, { companyId, wikiId: DEFAULT_WIKI_ID });\n  const valid = new Set(candidates.projects.map((p) => p.id));\n  return projectIds.filter((id) => valid.has(id));\n}","typeGuard":"function isLikelyProjectId(id) {\n  return typeof id === \"string\" && id.length > 0 && /^[a-zA-Z0-9_-]+$/.test(id);\n}","tryCatchPattern":"try {\n  await updatePaperclipIngestionProfile(ctx, { companyId, spaceSlug, profile });\n} catch (err) {\n  if (/Project belongs to another company or does not exist/.test(err.message)) {\n    const id = err.message.split(\": \").pop();\n    profile.sourceScopes = profile.sourceScopes.map((s) =>\n      s.kind === \"selected_projects\" ? { ...s, projectIds: s.projectIds.filter((p) => p !== id) } : s);\n    return updatePaperclipIngestionProfile(ctx, { companyId, spaceSlug, profile });\n  }\n  throw err;\n}","preventionTips":["Refresh candidates before saving the profile.","Scope project lookups to the current company.","Drop archived/deleted ids from cached pickers."],"tags":["validation","ingestion","wiki","company-scope","paperclip"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}