Hmbown/CodeWhale · error
cloud job id must look like cloud_
Error message
cloud job id must look like cloud_<hex>
What it means
The cloud job store refuses to build a filesystem path for a job id that does not match the expected shape `cloud_<hex>`. Job ids are used directly as filenames (`<id>.json`), so this check prevents path traversal and malformed ids from reaching the disk before any save or load happens.
Solutions
- Print/inspect the id and ensure it matches `cloud_` followed by hexadecimal characters (e.g. `cloud_deadbeef`).
- Trim whitespace and strip surrounding quotes/brackets when the id comes from user input, config, or logs.
- Obtain the id from the API that created the job (e.g. a DispatchOutcome or the store's own listing) instead of hand-constructing it.
- If old records use a legacy id format, migrate or re-create them; the validator is intentionally strict.
Example fix
// before
store.load("abc123")?;
// after
let id = raw_id.trim();
if valid_job_id(id) { store.load(id)?; } Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_job_id(id: &str) -> bool {
id.starts_with("cloud_") && !id.as_bytes()[6..].is_empty()
&& id[6..].bytes().all(|b| b.is_ascii_hexdigit())
} Type guard
fn valid_job_id(id: &str) -> bool {
let hex = id.strip_prefix("cloud_").unwrap_or("");
!hex.is_empty() && hex.bytes().all(|b| b.is_ascii_hexdigit())
} Try / catch
match store.load(id) {
Ok(job) => job,
Err(e) if e.to_string().contains("cloud_<hex>") => {
eprintln!("invalid job id '{id}': expected cloud_<hex>");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Always obtain ids from the store listing or dispatch result, never free text.
- Trim and normalize user input before use.
- Centralize the id format check in one helper (valid_job_id) and reuse it at every input boundary.
- Add a form/UI-level regex check (^cloud_[0-9a-f]+$) before submission.
When it happens
Trigger: Calling CloudJobStore::save or CloudJobStore::load (or higher-level flows that pass through them, e.g. confirm_job) with an id string that is empty, lacks the `cloud_` prefix, or whose suffix is not hexadecimal.
Common situations: Passing a user-typed or clipboard-pasted job id that includes whitespace or a short label; persisting/reusing an id from a different system; parsing an id out of a log line and picking up surrounding text; older persisted records written before the `cloud_` convention was introduced.
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
- Automation lock must be a regular file
- Codewhale credentials path must be a directory
- CodewhalePet/1
- DeepSeek Harness credentials line
- Downloaded release artifact must be a regular file
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/4b7bfe9df44262ab.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/cloud_dispatch.rs:368
for entry in fs::read_dir(&self.root).context("failed to read cloud-jobs")? {
let entry = entry?;
let name = entry.file_name();
let name = name.to_string_lossy();
if !name.starts_with("cloud_") || !name.ends_with(".json") {
continue;
}
let body = fs::read(entry.path())?;
if let Ok(job) = serde_json::from_slice::<CloudJob>(&body) {
jobs.push(job);
}
}
jobs.sort_by_key(|a| std::cmp::Reverse(a.created_unix));
Ok(jobs)
}
fn job_path(&self, id: &str) -> Result<PathBuf> {
if !valid_job_id(id) {
bail!("cloud job id must look like cloud_<hex>");
}
Ok(self.root.join(format!("{id}.json")))
}
}
/// Classify a git remote. Named `github` / `cnb` / `gitee` win over URL.
pub fn classify_remote(name: &str, url: &str) -> Option<Forge> {
match name.trim().to_ascii_lowercase().as_str() {
"github" => Some(Forge::Github),
"cnb" => Some(Forge::Cnb),
"gitee" => Some(Forge::Gitee),
_ => classify_url(url),
}
}
/// True when `branch` is a forge default that a non-force push could
/// fast-forward past review (`main` / `master` / `HEAD`).
pub fn is_forge_default_branch(branch: &str) -> bool {View on GitHub (pinned to 73e0f67d83)