{"record":{"id":"14ff378935e542e2","repo":"astrid-runtime/astrid","slug":"running-daemon-does-not-expose-workspace-selection","errorCode":null,"errorMessage":"running daemon does not expose workspace selection metadata; run `astrid restart`","messagePattern":"running daemon does not expose workspace selection metadata; run `astrid restart`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/daemon/workspace_fingerprint.rs","lineNumber":70,"sourceCode":"    let resolved_home = AstridHome::resolve().context(\"failed to resolve Astrid home\")?;\n    let mut fingerprints = Vec::new();\n    for layout in layouts_for_workspace_root(&root, &resolved_home) {\n        let fingerprint = checked_workspace_selection_fingerprint(&root, &layout)\n            .context(\"selected workspace state path is unsafe\")?;\n        if !fingerprints.contains(&fingerprint) {\n            fingerprints.push(fingerprint);\n        }\n    }\n    Ok(fingerprints)\n}\n\n/// Validate the versioned readiness metadata emitted by the daemon.\npub(crate) fn validate_daemon_workspace_metadata(\n    metadata: &str,\n    expected: &[String],\n) -> Result<()> {\n    let Some(actual) = metadata.trim().strip_prefix(\"v1:\") else {\n        anyhow::bail!(\n            \"running daemon does not expose workspace selection metadata; run `astrid restart`\"\n        );\n    };\n    if !expected.iter().any(|fingerprint| fingerprint == actual) {\n        anyhow::bail!(\n            \"running daemon belongs to another project or workspace layout; run `astrid restart` from this project\"\n        );\n    }\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn runtime_home_accepts_aos_fingerprint_for_default_cli_layout() {\n        let home_root = tempfile::tempdir().expect(\"home root\");","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/daemon/workspace_fingerprint.rs#L52-L88","documentation":"validate_daemon_workspace_metadata parses the daemon's versioned readiness metadata, which must have the prefix `v1:` followed by a workspace fingerprint. If the metadata lacks that prefix, the running daemon predates the workspace-selection metadata feature and cannot be verified, so the CLI fails and asks you to restart the daemon.","triggerScenarios":"Connecting to a daemon started by an older CLI version that emits no `v1:`-prefixed metadata string; metadata is empty or whitespace; ensure_daemon_workspace_matches inspects the readiness payload during connect.","commonSituations":"Upgrading the astrid CLI while an old daemon from a previous version is still running; long-lived daemon started before a CLI update.","solutions":["Run `astrid restart` so the daemon is relaunched with the current CLI that emits `v1:` metadata","Stop the stale daemon manually and start it again with the upgraded CLI","Verify CLI and daemon versions match (`astrid --version` vs daemon build)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// caller-side check before connecting\nlet metadata_ok = daemon_metadata.starts_with(\"v1:\");\nif !metadata_ok { println!(\"daemon too old; run astrid restart\"); }","typeGuard":null,"tryCatchPattern":"if let Err(e) = ensure_daemon_workspace_matches(&home, &expected).await {\n    if e.to_string().contains(\"workspace selection metadata\") {\n        run_restart(&home).await?;\n    } else { return Err(e); }\n}","preventionTips":["Restart the daemon after every CLI upgrade","Pin CLI and daemon to matching versions in CI","Treat `v1:` metadata absence as a signal to restart, not to bypass validation"],"tags":["daemon","metadata","version-compatibility"],"backgroundTag":"deprecated-api-usage","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}