paperclipai/paperclip · error
projectId is required for project workspace diffs
Error message
projectId is required for project workspace diffs
What it means
Thrown by the workspace-diff plugin (worker.ts:60) only when `params.entityType === "project_workspace"` and `projectId` is missing. Project-workspace diffs must enumerate a project's workspaces via `ctx.projects.listWorkspaces(projectId, companyId)`, so a projectId is mandatory in that branch (it is optional for plain execution workspaces).
Source
Thrown at packages/plugins/plugin-workspace-diff/src/worker.ts:60
: null;
}
const plugin = definePlugin({
async setup(ctx) {
ctx.logger.info(`${PLUGIN_NAME} plugin setup`);
const workspaceDiff = workspaceDiffService();
ctx.data.register("workspace-diff", async (params: Record<string, unknown>) => {
const workspaceId = readString(params.workspaceId);
const companyId = readString(params.companyId);
if (!workspaceId || !companyId) {
throw new Error("workspaceId and companyId are required");
}
if (params.entityType === "project_workspace") {
const projectId = readString(params.projectId);
if (!projectId) {
throw new Error("projectId is required for project workspace diffs");
}
const workspaces = await ctx.projects.listWorkspaces(projectId, companyId);
const workspace = workspaces.find((candidate) => candidate.id === workspaceId);
if (!workspace) {
throw new Error("Workspace not found");
}
return workspaceDiff.getDiff({
id: workspace.id,
companyId,
cwd: workspace.path,
baseRef: resolveDefaultBaseRef({
projectWorkspaceDefaultRef: workspace.defaultRef,
projectWorkspaceRepoRef: workspace.repoRef,
}),
}, workspaceDiffQuerySchema.parse(params));
}
const workspace = await ctx.executionWorkspaces.get(workspaceId, companyId);View on GitHub (pinned to 67001ec6eb)
Solutions
- When `entityType` is `"project_workspace"`, always include a non-empty `projectId`.
- If you actually want an execution-workspace diff, omit `entityType` (or set it to anything other than `"project_workspace"`) and the projectId requirement does not apply.
- Validate the (entityType, projectId) pairing at the call site before dispatch.
Example fix
// before
ctx.data.fetch("workspace-diff", { workspaceId, companyId, entityType: "project_workspace" });
// after
ctx.data.fetch("workspace-diff", { workspaceId, companyId, entityType: "project_workspace", projectId }); Defensive patterns
Strategy: validation
Validate before calling
function assertProjectWorkspaceParams(input) {
if (input.entityType !== "project_workspace") return input;
const projectId = typeof input.projectId === "string" ? input.projectId.trim() : "";
if (!projectId) {
throw new TypeError("entityType 'project_workspace' requires a non-empty projectId");
}
return { ...input, projectId };
} Type guard
function isCompleteProjectWorkspaceDiff(p): boolean {
return p?.entityType !== "project_workspace" || (typeof p?.projectId === "string" && p.projectId.trim().length > 0);
} Prevention
- Treat (entityType === 'project_workspace') as requiring projectId by contract.
- For execution-workspace diffs, omit entityType entirely.
- Validate entityType/projectId pairing at the UI action dispatch boundary.
When it happens
Trigger: Requesting a diff with `entityType: "project_workspace"` but omitting `projectId`, or passing an empty/non-string projectId. The check fires after the workspaceId/companyId guard, so those must already be present.
Common situations: A caller sets entityType to project_workspace to get a primary-repo diff but forgets projectId, or reuses an execution-workspace params object (which lacks projectId) for a project-workspace diff.
Related errors
- workspaceId and companyId are required
- status is required
- path is required
- Workspace not found
- --payload must be a JSON object
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/7a00e2b75c576c61.
Report an issue: GitHub.