paperclipai/paperclip · error

Execution workspace cannot be closed right now

Error message

Execution workspace cannot be closed right now

What it means

The archive request reached the close-readiness gate and readiness reported the workspace is not closable right now (e.g. live runtime services, pending operations), so the transition to archived is refused.

Solutions

  1. This is an authorization rule, not a bug: perform the action with an actor that satisfies the stated constraint (board user, the owning agent, or an in-scope resource).
  2. If access should be allowed, verify the actor's credentials/company scope and the resource's ownership before retrying.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/routes/execution-workspaces.ts:752 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18). Data as JSON: /api/errors/cec3a51d9f39f205. Report an issue: GitHub.

Appendix: source

Thrown at server/src/routes/execution-workspaces.ts:1184

      patch.metadata = req.body.config === undefined
        ? requestedMetadata
        : mergeExecutionWorkspaceConfig(requestedMetadata, req.body.config ?? null);
    }
    let workspace = existing;
    let cleanupWarnings: string[] = [];
    const configForCleanup = readExecutionWorkspaceConfig(
      ((patch.metadata as Record<string, unknown> | null | undefined) ?? (existing.metadata as Record<string, unknown> | null)) ?? null,
    );

    if (req.body.status === "archived" && existing.status !== "archived") {
      const readiness = await svc.getCloseReadiness(existing.id);
      if (!readiness) {
        res.status(404).json({ error: "Execution workspace not found" });
        return;
      }

      if (readiness.state === "blocked") {
        res.status(409).json({
          error: readiness.blockingReasons[0] ?? "Execution workspace cannot be closed right now",
          closeReadiness: readiness,
        });
        return;
      }

      const closedAt = new Date();
      // Archive under the per-workspace lifecycle lock. The service takes the same
      // lock as a reopen, raises the lifecycle generation, and clears the
      // reopen-pending flag. The lock stops a concurrent reopen from publishing an
      // active row between the status re-check and this archive write, so the
      // destruction fence below never deletes a worktree that a reopen rebuilt.
      const archiveResult = await svc.archiveWorkspaceUnderLifecycleLock({
        id,
        patch,
        closedAt,
      });
      if (!archiveResult) {

View on GitHub (pinned to a7e689b3c3)