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
- 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.
- Retry the create after fixing the underlying cause (free resources, fix host connectivity).
- Inspect the spec returned by the builder (host/path/identity) for values that pass validation but fail at runtime.
- 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
- Treat a rejected create promise as a hard failure in scripts — do not swallow it.
- Inspect the dock's retained failed row for the specific outcome.error when the thrown message is generic.
- Fix runtime preconditions (host reachability, resources) before retrying a failed create.
- Log editor.debug/error output around awaitCreateOutcome to capture causes the generic message omits.
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
- ${built.error}
- project path does not exist
- failed
- producerError
- could not open : no tokio runtime available for container…
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)