astrid-runtime/astrid · error

canonical Astrid workspace requires the kernel workspace…

Error message

canonical Astrid workspace requires the kernel workspace branch service

What it means

Thrown when assembling the canonical Astrid workspace: the kernel's `workspace_branches` service is `None` at the point the builder calls `with_workspace_branches`. The workspace branch service manages per-workspace branch state, which the canonical workspace requires, so startup aborts instead of creating a workspace without branch tracking.

Solutions

  1. Initialize and set the workspace branch service on the kernel before starting the canonical workspace
  2. Update kernel construction to call the workspace-branches builder method (likely newly required after a version change)
  3. Audit all kernel instantiation sites (including tests) so none skip workspace branch setup

Example fix

// before
let kernel = AstridKernel::builder()
    .with_principal_store(store)
    .build(); // workspace_branches left unset
// after
let kernel = AstridKernel::builder()
    .with_principal_store(store)
    .with_workspace_branches(branch_service)
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if kernel.workspace_branches().is_none() {
    return Err(anyhow!("workspace branch service required for canonical workspace"));
}

Type guard

fn has_workspace_branches(kernel: &AstridKernel) -> bool {
    kernel.workspace_branches().is_some()
}

Prevention

When it happens

Trigger: Starting the native capsule runtime / canonical Astrid workspace while `self.workspace_branches` was never populated (lib.rs:1947, the `with_workspace_branches(...)` call in the builder chain).

Common situations: Kernel instances built without the workspace-branch initialization step; partial test fixtures that stub other services but omit workspace branches; upgrades where new required builder wiring (workspace branches) was not added to existing kernel construction code.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/666416ad988232b7. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-kernel/src/lib.rs:1947

            // Durable home VFS authority is threaded separately through the
            // UID-bound principal store. Do not pass a native PrincipalHome
            // path into the steady-state capsule context.
            None,
            kv,
            Arc::clone(&self.event_bus),
            capsule_listener,
        )
        .with_astrid_workspace()
        .with_principal_storage(
            self.principal_store.clone().ok_or_else(|| {
                anyhow::anyhow!(
                    "native capsule runtime requires the authoritative principal store"
                )
            })?,
            self.principal_directory.clone(),
        )
        .with_workspace_branches(self.workspace_branches.clone().ok_or_else(|| {
            anyhow::anyhow!(
                "canonical Astrid workspace requires the kernel workspace branch service"
            )
        })?)
        .with_process_storage_mount_broker(
            self.process_storage_mount_broker
                .get()
                .cloned()
                .ok_or_else(|| anyhow::anyhow!("native process storage mount broker unavailable"))?,
        )
        .with_registry(Arc::clone(&self.capsules))
        .with_session_token(Arc::clone(&self.session_token))
        .with_allowance_store(Arc::clone(&self.allowance_store))
        .with_identity_store(Arc::clone(&self.identity_store))
        .with_profile_cache(Arc::clone(&self.profile_cache))
        .with_overlay_registry(Arc::clone(&self.overlay_registry))
        // Thread the live group config so capsule invocation checks observe
        // runtime group mutations without requiring capsule reloads. Load-time
        // run-loop decisions take their own explicit snapshot.

View on GitHub (pinned to affd8760f4)