{"record":{"id":"df5ef4da0b6d81d1","repo":"Hmbown/CodeWhale","slug":"new-date-date-is-unavailable-in-workflow-scrip","errorCode":null,"errorMessage":"new Date()/Date() is unavailable in Workflow scripts: runs must be deterministic for record/replay","messagePattern":"new Date\\(\\)/Date\\(\\) 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":1036,"sourceCode":"        \"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;\n\n  const MAX_ITEMS = __MAX_ITEMS__;\n  const taskErrorText = (err) => String(err && err.message !== undefined ? err.message : err);","sourceCodeStart":1018,"sourceCodeEnd":1054,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/workflow-js/src/vm.rs#L1018-L1054","documentation":"Same invariant as scope_path, enforced independently in the scoped branch of the recent-entries query (native_memory.rs:431). When a Some(MemoryScope::Workspace) filter is applied, the store must resolve the workspace's MEMORY.md path to filter rows by source, and that resolution needs the workspace id. Without it there is no single source to filter on, so the query fails fast instead of guessing.","triggerScenarios":"Calling the recent/recall API with scope=Some(MemoryScope::Workspace) and workspace_id=None — typically the memory-search or memory-recall tool invoked from a directory where git remote.origin.url is absent, so the caller passes None through.","commonSituations":"Non-git working directories; repositories with no origin remote; scripted or headless use of the memory tool where the workspace root is not a checkout; unit tests calling the store directly with a Workspace scope filter but no id.","solutions":["Compute the id up front and skip the workspace filter when it cannot be derived: query with scope None (all scopes) or Some(Global) instead.","Ensure the process cwd is the git checkout and that `git config --get remote.origin.url` succeeds and is non-empty.","In library code, mirror the guard before calling: if scope == Workspace && workspace_id.is_none() { choose a different scope or return your own error }."],"exampleFix":"// before\nlet hits = store.recent(Some(MemoryScope::Workspace), None, 50)?;\n\n// after\nlet scope = match NativeMemoryStore::workspace_id(&cwd)? {\n    Some(_) => Some(MemoryScope::Workspace),\n    None => None, // no origin remote -> include all scopes\n};\nlet hits = store.recent(scope, workspace_id.as_deref(), 50)?;","handlingStrategy":"validation","validationCode":"let id = NativeMemoryStore::workspace_id(&cwd)?;\nlet (scope, ws) = match id.as_deref() {\n    Some(id) => (Some(MemoryScope::Workspace), Some(id)),\n    None => (None, None), // query across all scopes instead\n};\nlet entries = store.recent(scope, ws, limit)?;","typeGuard":"fn can_query_workspace_scope(cwd: &Path) -> bool {\n    NativeMemoryStore::workspace_id(cwd).map(|id| id.is_some()).unwrap_or(false)\n}","tryCatchPattern":"match store.recent(Some(MemoryScope::Workspace), ws_id, limit) {\n    Ok(rows) => rows,\n    Err(e) if e.to_string().contains(\"workspace scope requires a workspace id\") =>\n        store.recent(None, None, limit)?, // retry unscoped\n    Err(e) => return Err(e),\n}","preventionTips":["Never forward a Workspace scope filter without a workspace id; resolve both together.","Check `git config --get remote.origin.url` succeeds in the session cwd before enabling workspace-scoped recall UI.","Wrap store calls in a helper that takes (cwd, scope) and internally resolves or downgrades the scope."],"tags":["rust","native-memory","workspace","query","validation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}