paperclipai/paperclip · error · Error
Issue belongs to another company or does not exist: ${issueI
Error message
Issue belongs to another company or does not exist: ${issueId} What it means
Thrown during profile validation when ctx.issues.get(issueId, companyId) returns nullish for an id in a 'root_issues' scope. The lookup is company-scoped, so null means the issue is missing, deleted, belongs to another company, or is not a root issue retrievable by id. Protects ingestion from cross-company or stale references.
Source
Thrown at packages/plugins/plugin-llm-wiki/src/wiki/core.ts:1016
if (scope.kind === "company_all" && input.space.slug !== DEFAULT_SPACE_SLUG) {
throw new Error("Everything in the company is only available on the default wiki space.");
}
if (scope.kind === "selected_projects") {
if (scope.projectIds.length > MAX_PAPERCLIP_PROFILE_SELECTED_PROJECTS) {
throw new Error(`selected_projects exceeds the hard cap of ${MAX_PAPERCLIP_PROFILE_SELECTED_PROJECTS}.`);
}
for (const projectId of scope.projectIds) {
const project = await ctx.projects.get(projectId, input.companyId);
if (!project) throw new Error(`Project belongs to another company or does not exist: ${projectId}`);
}
}
if (scope.kind === "root_issues") {
if (scope.issueIds.length > MAX_PAPERCLIP_PROFILE_ROOT_ISSUES) {
throw new Error(`root_issues exceeds the hard cap of ${MAX_PAPERCLIP_PROFILE_ROOT_ISSUES}.`);
}
for (const issueId of scope.issueIds) {
const issue = await ctx.issues.get(issueId, input.companyId);
if (!issue) throw new Error(`Issue belongs to another company or does not exist: ${issueId}`);
}
}
}
}
export async function updatePaperclipIngestionProfile(ctx: PluginContext, input: {
companyId: string;
wikiId?: string | null;
spaceSlug?: string | null;
profile: unknown;
}): Promise<PaperclipIngestionProfileRead> {
const wikiId = normalizeWikiId(input.wikiId);
const space = await resolveSpace(ctx, { companyId: input.companyId, wikiId, spaceSlug: input.spaceSlug });
const current = await profileForSpace(ctx, input.companyId, space);
const profile = normalizePaperclipIngestionProfile(input.profile, { space, legacySettings: space.slug === DEFAULT_SPACE_SLUG ? await getEventIngestionSettings(ctx, input.companyId) : null });
await validatePaperclipIngestionProfile(ctx, { companyId: input.companyId, space, profile });
await updateSpace(ctx, {
companyId: input.companyId,View on GitHub (pinned to 67001ec6eb)
Solutions
- Call listPaperclipIngestionCandidates and only keep rootIssues ids it returns for the current company.
- Drop invalid ids before submission or prompt the user to re-pick.
- Confirm the companyId in the request owns every issueId.
- If issues were just created, ensure they are readable before referencing them.
Example fix
// before
profile.sourceScopes = [{ kind: "root_issues", issueIds: rawIssueIds }];
// after
const candidates = await listPaperclipIngestionCandidates(ctx, { companyId, wikiId });
const valid = new Set(candidates.rootIssues.map((i) => i.id));
profile.sourceScopes = [{
kind: "root_issues",
issueIds: rawIssueIds.filter((id) => valid.has(id)),
}]; Defensive patterns
Strategy: validation
Validate before calling
async function filterExistingRootIssues(ctx, companyId, issueIds) {
const candidates = await listPaperclipIngestionCandidates(ctx, { companyId, wikiId: DEFAULT_WIKI_ID });
const valid = new Set(candidates.rootIssues.map((i) => i.id));
return issueIds.filter((id) => valid.has(id));
} Type guard
function isLikelyIssueId(id) {
return typeof id === "string" && id.length > 0 && /^[a-zA-Z0-9_-]+$/.test(id);
} Try / catch
try {
await updatePaperclipIngestionProfile(ctx, { companyId, spaceSlug, profile });
} catch (err) {
if (/Issue belongs to another company or does not exist/.test(err.message)) {
const id = err.message.split(": ").pop();
profile.sourceScopes = profile.sourceScopes.map((s) =>
s.kind === "root_issues" ? { ...s, issueIds: s.issueIds.filter((p) => p !== id) } : s);
return updatePaperclipIngestionProfile(ctx, { companyId, spaceSlug, profile });
}
throw err;
} Prevention
- Use the candidate list to populate root-issue pickers.
- Confirm company ownership of every id.
- Avoid caching issue ids across long sessions.
When it happens
Trigger: Submitting a 'root_issues' scope containing a deleted, mistyped, cross-company, or non-existent issue id through updatePaperclipIngestionProfile.
Common situations: Stale id from a previously deleted issue; ids copied from another tenant; transient state right after issue creation; non-root issue id used where root issues are expected.
Related errors
- Project belongs to another company or does not exist: ${proj
- selected_projects exceeds the hard cap of ${MAX_PAPERCLIP_PR
- root_issues exceeds the hard cap of ${MAX_PAPERCLIP_PROFILE_
- Selected Wiki Maintainer agent was not found or is terminate
- Selected LLM Wiki project was not found.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/70c285e8cf60b902.
Report an issue: GitHub.