Hmbown/CodeWhale · error · io::Error

legacy spillover ownership requires a session id

Error message

legacy spillover ownership requires a session id

What it means

publish_legacy_spillover_ownership writes a sidecar that records which session owns a legacy spillover payload. It refuses to proceed when the session id is empty or whitespace-only, returning InvalidInput with this message, because an owner-less ownership record would be meaningless and unresolvable later.

Solutions

  1. Ensure the session is initialized before triggering spillover so a real session id reaches apply_spillover_inner.
  2. Check where session_id originates (context/session manager) and fix the code path that yields an empty value.
  3. In tests or scripts, pass an explicit non-empty session id instead of "".
  4. Add an early guard that fails loud at session creation if the generated id is empty.

Example fix

// before
publish_legacy_spillover_ownership(&payload, "", &bytes)?  // empty session id
// after
let sid = context.session_id.as_deref().unwrap_or_else(|| panic!("session id required"));
publish_legacy_spillover_ownership(&payload, sid, &bytes)?
Defensive patterns

Strategy: validation

Validate before calling

// guard before invoking the spillover path
if session_id.trim().is_empty() { return Err("spillover requires an initialized session id"); }

Type guard

fn has_session_id(id: &str) -> bool { !id.trim().is_empty() }

Try / catch

// rust
match apply_spillover(...) {
    Err(e) if e.to_string().contains("requires a session id") => {
        eprintln!("session not initialized; create a session before spillover");
    }
    other => other?,
}

Prevention

When it happens

Trigger: apply_spillover_inner calling publish_legacy_spillover_ownership with a session_id that is "" or contains only whitespace — typically when the session context was not initialized or the id was not propagated to the truncate/spillover path.

Common situations: Running a tool invocation outside a proper session (early startup, tests with a stub context); a session id field defaulted to empty string; regression in session-id plumbing after refactor.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/308d2aab34f522bf. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/truncate.rs:140

}

#[must_use]
pub(crate) fn legacy_spillover_ownership_path(payload_path: &Path) -> PathBuf {
    payload_path.with_extension("owner.json")
}

/// Publish the proof needed to retrieve a legacy-global spillover safely.
///
/// Payload publication happens first. If this atomic sidecar write fails, the
/// payload is deliberately left unowned and therefore inaccessible through
/// `retrieve_tool_result`; callers must not advertise a retrieval hint.
pub(crate) fn publish_legacy_spillover_ownership(
    payload_path: &Path,
    session_id: &str,
    bytes: &[u8],
) -> io::Result<PathBuf> {
    if session_id.trim().is_empty() {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "legacy spillover ownership requires a session id",
        ));
    }
    let ownership = LegacySpilloverOwnership {
        schema_version: LEGACY_SPILLOVER_OWNER_SCHEMA_VERSION,
        origin_session: session_id.to_string(),
        digest: crate::hashing::sha256_hex(bytes),
        size_bytes: bytes.len().try_into().unwrap_or(u64::MAX),
    };
    let sidecar = legacy_spillover_ownership_path(payload_path);
    let encoded = serde_json::to_vec_pretty(&ownership)
        .map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
    crate::utils::write_atomic(&sidecar, &encoded)?;
    Ok(sidecar)
}

pub(crate) fn read_legacy_spillover_ownership(

View on GitHub (pinned to 73e0f67d83)