Hmbown/CodeWhale · error
invalid session goal revision
Error message
invalid session goal revision
What it means
When a goal_id is present, it must be non-empty and at most 128 bytes; otherwise SessionGoalState::validate rejects the state with this InvalidData error. This guards the revision identifier used to detect concurrent goal changes.
Solutions
- Fix or remove the goal_id field in the goal file (a valid non-empty ID ≤128 chars, or null).
- Delete the goal file and recreate the goal via the TUI.
- Use the session's own goal commands to regenerate a valid revision instead of hand-crafting IDs.
Example fix
// before
{"goal_id": "", ...}
// after
{"goal_id": "g-8f14e45f", ...} // or remove the field / set null Defensive patterns
Strategy: validation
Validate before calling
fn goal_id_ok(id: &Option<String>) -> bool {
id.as_ref().map(|i| !i.is_empty() && i.len() <= 128).unwrap_or(true)
} Try / catch
match load_goal(path) {
Err(e) if e.to_string().contains("invalid session goal revision") => {
eprintln!("goal_id must be non-empty and <=128 chars, or absent");
}
other => other?,
} Prevention
- Let Codewhale generate goal_ids; don't hand-craft them.
- Validate ID length before writing goal JSON programmatically.
- Set goal_id to null rather than "" when clearing it.
When it happens
Trigger: Loading a goal state where goal_id is Some("") or a string longer than 128 bytes/chars.
Common situations: Hand-edited goal files setting goal_id to an empty string; scripts generating oversized IDs; corruption or truncation of the goal file.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- cloud job id must look like cloud_
- DeepSeek Harness credentials line
- {error}
- goal snapshot has no objective
- goal snapshot has unsupported status
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/b3d5332624952df9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/session_manager.rs:833
self.schema_version, CURRENT_SESSION_GOAL_SCHEMA_VERSION
),
));
}
let objective = self.objective.trim();
if objective.is_empty() || objective.chars().count() > MAX_SESSION_GOAL_OBJECTIVE_CHARS {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"Session goal objective must contain 1..={MAX_SESSION_GOAL_OBJECTIVE_CHARS} characters"
),
));
}
if self
.goal_id
.as_ref()
.is_some_and(|id| id.is_empty() || id.len() > 128)
{
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"invalid session goal revision",
));
}
codewhale_protocol::validate_goal_stall_state(
self.last_gap_fingerprint.as_deref(),
self.repeated_gap_count,
self.last_gap_pass,
self.continuation_count,
)
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))
}
#[must_use]
pub fn to_runtime_snapshot(&self) -> GoalSnapshot {
GoalSnapshot {
goal_id: self.goal_id.clone(),
objective: Some(self.objective.clone()),View on GitHub (pinned to 73e0f67d83)