paperclipai/paperclip · error · HttpError
cross_company_workspace
cross_company_workspace
Error message
Project workspace belongs to another company
What it means
Cross-tenant guard in targetProjectWorkspaceCandidate: the project/workspace ids supplied for an explicit workspace target resolve to rows owned by a different company than the issue's. The mismatch is rejected before any path resolution so one tenant can never address another tenant's workspace files.
Source
Thrown at server/src/services/workspace-file-resources.ts:1056
return issue;
}
async function targetProjectWorkspaceCandidate(
issue: IssueRow,
target: WorkspaceTargetInput,
): Promise<WorkspaceCandidate | null> {
const projectId = target.projectId ?? null;
const workspaceId = target.workspaceId ?? null;
if (!projectId && !workspaceId) return null;
if (!projectId || !workspaceId) {
throw unprocessable("Workspace file target requires both projectId and workspaceId", { code: "invalid_target" });
}
const [project] = await db.select().from(projects).where(eq(projects.id, projectId)).limit(1);
const [workspace] = await db.select().from(projectWorkspaces).where(eq(projectWorkspaces.id, workspaceId)).limit(1);
if (!project || !workspace) throw notFound("Project workspace not found");
if (project.companyId !== issue.companyId || workspace.companyId !== issue.companyId) {
throw new HttpError(403, "Project workspace belongs to another company", { code: "cross_company_workspace" });
}
if (workspace.projectId !== project.id) {
throw unprocessable("Workspace does not belong to the selected project", { code: "workspace_project_mismatch" });
}
return candidateFromProjectWorkspace(workspace, { id: project.id, name: project.name });
}
async function listCandidates(
issue: IssueRow,
selector: WorkspaceFileSelector,
target: WorkspaceTargetInput = {},
): Promise<WorkspaceCandidate[]> {
const explicitTarget = await targetProjectWorkspaceCandidate(issue, target);
if (explicitTarget) return [explicitTarget];
const candidates: WorkspaceCandidate[] = [];
if ((selector === "auto" || selector === "execution") && issue.projectId) {View on GitHub (pinned to 120ae5428f)
Solutions
- Access the workspace through a project that belongs to your company; cross-company workspace access is forbidden.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at server/src/services/workspace-file-resources.ts:1056 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18).
Data as JSON: /api/errors/44ce27d6d443d388.
Report an issue: GitHub.