Hmbown/CodeWhale · error · anyhow::Error

workspace scope requires a workspace id

Error message

workspace scope requires a workspace id

What it means

Native memory's remember() writes a note to a per-scope Markdown file; the Workspace scope needs a workspace id to compute its path, and None is rejected immediately after normalize_note() validated the text. This is a caller-contract violation, not an environmental failure — the note is treated as data, never instructions.

Source

Thrown at crates/tui/src/native_memory.rs:210

            fs::write(&target, content)?;
            self.reindex_file(&target)?;
            Ok(true)
        })
    }

    /// Append a reviewed note to the selected Markdown source and refresh its
    /// index. The note is treated as data, never as an instruction.
    pub fn remember(
        &self,
        scope: MemoryScope,
        workspace_id: Option<&str>,
        note: &str,
    ) -> Result<MemoryHit> {
        let note = normalize_note(note)?;
        let path = match scope {
            MemoryScope::Global => self.global_path(),
            MemoryScope::Workspace => self.workspace_path(
                workspace_id.ok_or_else(|| anyhow!("workspace scope requires a workspace id"))?,
            )?,
        };
        self.with_write_lock(|| {
            ensure_memory_file(&path)?;
            let before = fs::read_to_string(&path).unwrap_or_default();
            let line_start = before.lines().count().saturating_add(2);
            let mut file = OpenOptions::new()
                .create(true)
                .append(true)
                .open(&path)
                .with_context(|| format!("open memory source {}", path.display()))?;
            if !before.is_empty() && !before.ends_with('\n') {
                writeln!(file)?;
            }
            writeln!(file, "\n- {note}")?;
            file.sync_data()?;
            self.reindex_file(&path)?;
            let line_end = line_start;

View on GitHub (pinned to 8880682c63)

Solutions

  1. Pass the session's workspace id whenever scope is Workspace
  2. When no workspace context exists, record with MemoryScope::Global instead
  3. Fix the caller to resolve the workspace id before choosing the scope

Example fix

// before
memory.remember(MemoryScope::Workspace, None, note)?;

// after
let scope = match workspace_id {
    Some(_) => MemoryScope::Workspace,
    None => MemoryScope::Global,
};
memory.remember(scope, workspace_id, note)?;
Defensive patterns

Strategy: validation

Validate before calling

```rust
// Derive the scope from the id you actually have, before calling remember():
let scope = match workspace_id {
    Some(_) => MemoryScope::Workspace,
    None => MemoryScope::Global,
};
memory.remember(scope, workspace_id, note)?;
```

Type guard

```rust
fn requires_workspace_id(scope: MemoryScope) -> bool {
    matches!(scope, MemoryScope::Workspace)
}
```

Prevention

When it happens

Trigger: Calling remember(MemoryScope::Workspace, None, note): the remember tool invoked with scope=workspace while the session had no workspace context or the caller dropped the workspace id.

Common situations: Sessions started outside any workspace directory; tool wiring forwarding the scope but not the id; scripted calls hardcoding scope=workspace.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/adf7689a910fb882. Report an issue: GitHub.