{"record":{"id":"71bab292858eda19","repo":"Hmbown/CodeWhale","slug":"name-is-unavailable-in-workflow-scripts-runs-m","errorCode":null,"errorMessage":"${name} is unavailable in Workflow scripts: runs must be deterministic for record/replay","messagePattern":"(.+?) is unavailable in Workflow scripts: runs must be deterministic for record/replay","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/workflow-js/src/vm.rs","lineNumber":1033,"sourceCode":"        \"explore\" | \"explorer\" | \"scout\" | \"plan\" | \"planner\" | \"review\" | \"reviewer\"\n        | \"verify\" | \"verifier\" => Some(TaskRoleKind::ReadOnly),\n        \"general\" | \"worker\" => Some(TaskRoleKind::General),\n        \"implement\" | \"implementer\" | \"builder\" => Some(TaskRoleKind::Implementer),\n        _ => None,\n    }\n}\n\n/// The JS prelude injected before every script: determinism bans, the\n/// `task`/`parallel`/`pipeline`/`log`/`phase` stdlib (design §7), and the\n/// `budget` global.\nfn prelude() -> String {\n    PRELUDE_TEMPLATE.replace(\"__MAX_ITEMS__\", &PARALLEL_MAX_ITEMS.to_string())\n}\n\nconst PRELUDE_TEMPLATE: &str = r#\"\"use strict\";\n(() => {\n  const banned = (name) => () => {\n    throw new Error(name + \" is unavailable in Workflow scripts: runs must be deterministic for record/replay\");\n  };\n  const BannedDate = function Date() {\n    throw new Error(\"new Date()/Date() is unavailable in Workflow scripts: runs must be deterministic for record/replay\");\n  };\n  BannedDate.now = banned(\"Date.now()\");\n  BannedDate.parse = banned(\"Date.parse()\");\n  BannedDate.UTC = banned(\"Date.UTC()\");\n  globalThis.Date = BannedDate;\n  Math.random = banned(\"Math.random()\");\n\n  // Capture temporary host bindings into this closure, then strip them from\n  // globalThis so scripts only see the documented Workflow surface (#4129).\n  const hostTask = __workflow_task;\n  const hostLog = __workflow_log;\n  const hostPhase = __workflow_phase;\n  const hostBudgetTotal = __workflow_budget_total;\n  const hostBudgetSpent = __workflow_budget_spent;\n  const hostBudgetRemaining = __workflow_budget_remaining;","sourceCodeStart":1015,"sourceCodeEnd":1051,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/workflow-js/src/vm.rs#L1015-L1051","documentation":"Thrown by NativeMemoryStore::scope_path when a memory operation is scoped to MemoryScope::Workspace but workspace_id is None. Workspace memory is stored per-repository under root/workspace/<id>/MEMORY.md, so an identifier is mandatory to pick the directory. The id is normally derived by hashing the git remote.origin.url (NativeMemoryStore::workspace_id), which returns None for non-git directories or repos without an origin remote.","triggerScenarios":"Calling remember/edit/retire with MemoryScope::Workspace and workspace_id=None; e.g. store.remember(MemoryScope::Workspace, None, \"note\"). The tool layer (tools/native_memory.rs, tools/remember.rs) hits this when the session's workspace has no derivable git origin, so no id is passed down.","commonSituations":"Running the TUI in a plain folder that is not a git repository; a freshly created repo that has no `origin` remote yet; a detached worktree cloned without remotes; tests that construct MemoryScope::Workspace directly without first computing an id.","solutions":["Derive the id first and bail out early: let id = NativeMemoryStore::workspace_id(cwd)?; if None, fall back to MemoryScope::Global or surface 'workspace memory requires a git origin remote' to the user.","If you are in a repo, add an origin remote: git remote add origin <url>, then retry.","If workspace isolation is not needed, call the same API with MemoryScope::Global, which needs no id.","In tests, pass a fixed id (e.g. Some(\"repo-a\")) like native_memory/tests.rs does."],"exampleFix":"// before\nstore.remember(MemoryScope::Workspace, None, \"note\")?;\n\n// after\nlet id = NativeMemoryStore::workspace_id(&cwd)?\n    .context(\"workspace memory requires a git origin remote\")?;\nstore.remember(MemoryScope::Workspace, Some(&id), \"note\")?;","handlingStrategy":"validation","validationCode":"let workspace_id = NativeMemoryStore::workspace_id(&cwd)?;\nlet scope = match (&workspace_id, wanted_scope) {\n    (Some(_), MemoryScope::Workspace) => MemoryScope::Workspace,\n    (None, MemoryScope::Workspace) => MemoryScope::Global, // or bail with your own message\n    (_, other) => other,\n};\nstore.remember(scope, workspace_id.as_deref(), note)?;","typeGuard":"fn workspace_scope_available(cwd: &Path) -> bool {\n    Command::new(\"git\").arg(\"-C\").arg(cwd)\n        .args([\"config\", \"--get\", \"remote.origin.url\"])\n        .output().map(|o| o.status.success() && !o.stdout.trim().is_empty()).unwrap_or(false)\n}","tryCatchPattern":"match store.remember(MemoryScope::Workspace, workspace_id.as_deref(), note) {\n    Ok(_) => {}\n    Err(e) if e.to_string().contains(\"workspace scope requires a workspace id\") => {\n        // degrade to global scope or tell the user to add an origin remote\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always derive workspace_id via NativeMemoryStore::workspace_id before any Workspace-scoped call.","Treat a None id as 'workspace memory unavailable' and fall back to Global or inform the user.","Ensure repos used with workspace memory have `git remote add origin <url>` set.","In tests, pass a deterministic Some(\"repo-x\") id like the native memory test-suite does."],"tags":["rust","native-memory","workspace","validation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}