sinelaw/fresh · error

workspace creation failed

Error message

workspace creation failed

What it means

After the orchestrator starts a pending workspace via startPendingWorkspace, it awaits awaitCreateOutcome; if the creation outcome is not ok, the stored outcome.error is thrown (falling back to the generic 'workspace creation failed' when no specific message was recorded). The comment stresses the design: a failed create must reject the caller's promise — and thus fail its script — rather than return a result object that could be mistaken for a workspace. The dock keeps the row so a human can retry or dismiss.

Solutions

  1. Check the editor dock/log for the failing workspace row and any more specific error recorded there, since the thrown message may be the generic fallback.
  2. Retry the create after fixing the underlying cause (free resources, fix host connectivity).
  3. Inspect the spec returned by the builder (host/path/identity) for values that pass validation but fail at runtime.
  4. If the generic message appears repeatedly with no detail, capture editor.debug/error logs around awaitCreateOutcome to find the real cause.

Example fix

// before
const ws = await orchestrator.createWorkspace(options); // rejects with 'workspace creation failed'
// after
try {
  const ws = await orchestrator.createWorkspace(options);
} catch (e) {
  editor.error(`create failed: ${e}; check dock row and logs for detail`);
  // surface outcome.error or retry with corrected options
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: make sure the spec's inputs are sound before starting the pending workspace
if (spec.projectPath && !fs.existsSync(spec.projectPath)) throw new Error("path missing before create");

Type guard

function isCreateOutcome(o) { return typeof o === "object" && o !== null && typeof o.ok === "boolean"; }
function isWorkspaceResult(r) { return typeof r.workspaceId === "string" && r.workspaceId !== ""; }

Try / catch

try {
  const ws = await createWorkspaceWithOutcome(options);
  if (!isWorkspaceResult(ws)) throw new Error("create returned non-workspace");
} catch (e) {
  // the dock keeps the failed row — check it for the specific cause, then retry or dismiss
  editor.error(`workspace create rejected: ${e}`);
}

Prevention

When it happens

Trigger: Calling the workspace-create API when the underlying create operation fails: the remote/local spawn fails, the backend reports an error outcome, or awaitCreateOutcome resolves with ok=false and no error message (yielding the generic fallback string).

Common situations: Backend process crashed or refused the create (port conflicts, resource limits); invalid spec that passed pre-validation but failed at spawn time; infrastructure issues on a remote host; a bug/timeout leaving the outcome without an error message so only the generic text appears.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/c624669b8f7b738f. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor/plugins/orchestrator.ts:10459

    // Worktree by default (the dialog's default too); `runLocalCreate` demotes
    // it to false on its own when the path isn't a git tree.
    createWorktree: options.worktree ?? true,
  });
}

async function newWorkspace(
  options: NewWorkspaceOptions = {},
): Promise<AgentLaunchResult> {
  // Before `specForNewWorkspace`, which rejects a bad host / missing path.
  await yieldToCaller();
  const spec = specForNewWorkspace(options);
  const pendingId = await startPendingWorkspace(spec, { visit: options.visit ?? false });
  const outcome = await awaitCreateOutcome(pendingId);
  if (!outcome.ok) {
    // Thrown, not returned: a failed create must reject the caller's promise
    // (and so fail its script), not hand it a result object it might mistake
    // for a workspace. The dock keeps the row for a human to retry or dismiss.
    throw new Error(outcome.error || "workspace creation failed");
  }
  return {
    workspaceId: outcome.workspaceId ?? "",
    windowId: outcome.windowId ?? 0,
    root: outcome.root ?? "",
  };
}

function listWorkspaces(): WorkspaceSummary[] {
  // Reconcile first: a workspace created seconds ago (by a script, or by
  // the dialog) is only in the model once the host's window list has been
  // folded in, and a caller listing right after creating should see it.
  reconcileSessions();
  const windows = editor.listWindows();
  const activeId = editor.activeWindow();
  return [...orchestratorSessions.values()].map((session) => {
    const win = windows.find((w) => w.id === session.id);
    const git = session.git?.info;

View on GitHub (pinned to 67894ca546)