Hmbown/CodeWhale · error
state subdir must not be empty
Error message
state subdir must not be empty
What it means
`ensure_safe_state_subdir` defensively validates the state subdirectory string used to locate state under the state root. An empty subdir is rejected because it is not a valid single relative path component and would silently resolve to the state root itself.
Solutions
- Pass a non-empty relative subdir such as `"sessions"`
- Provide a default (`"sessions"`) when the config/env value is empty
- If the state root itself is intended, call the root-path API instead of the subdir one
Example fix
// before
let dir = state_dir_in("")?;
// after
let dir = state_dir_in("sessions")?; Defensive patterns
Strategy: validation
Validate before calling
fn valid_subdir(subdir: &str) -> bool { !subdir.is_empty() } Try / catch
match state_dir_in(subdir) {
Err(e) if e.to_string().contains("subdir must not be empty") => {
state_dir_in("sessions")
}
result => result,
} Prevention
- Never pass user/env-supplied strings directly as subdir without a non-empty check
- Default to a hardcoded component like `"sessions"` when unset
- Keep subdir values hardcoded at call sites as the module intends
When it happens
Trigger: Calling a state-path helper that routes through `ensure_safe_state_subdir` with `subdir = ""`. In-tree callers pass hardcoded values like `"sessions"` or `"."`, so this fires only with an empty string from a caller-built path.
Common situations: Building the subdir from an env var or config value that is unset/empty; a format/trim bug dropping the segment; forwarding an empty `--state-subdir` style CLI flag.
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
- state subdir must not be an absolute path
- state subdir must not contain a root or prefix
- state subdir must not contain parent-dir (..) components
- budget baseline_receipt path changed
- Codewhale credentials directory has an unsupported component
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1fc4139ff0011dd1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/lib.rs:5723
}
/// Resolve the legacy DeepSeek home directory (`$HOME/.deepseek`).
///
/// Always returns the legacy path regardless of whether it exists.
pub fn legacy_deepseek_home() -> Result<PathBuf> {
codewhale_paths::legacy_deepseek_home().context("failed to resolve home directory")
}
/// Reject state subdirs that could escape the state root via path injection.
///
/// `ensure_state_dir` / `resolve_state_dir` are public APIs taking an arbitrary
/// subdir string; every in-tree caller passes a hardcoded single component
/// (e.g. `"sessions"`, `"."`). This validates defensively so a future caller
/// can never traverse out of the state root via `..` components or an absolute
/// path. Nested relative paths such as `"a/b"` are permitted.
fn ensure_safe_state_subdir(subdir: &str) -> Result<()> {
if subdir.is_empty() {
bail!("state subdir must not be empty");
}
let path = std::path::Path::new(subdir);
if path.is_absolute() {
bail!("state subdir must not be an absolute path: {subdir}");
}
if path.components().any(|c| {
matches!(
c,
std::path::Component::RootDir | std::path::Component::Prefix(_)
)
}) {
bail!("state subdir must not contain a root or prefix: {subdir}");
}
if path
.components()
.any(|c| matches!(c, std::path::Component::ParentDir))
{
bail!("state subdir must not contain parent-dir (..) components: {subdir}");View on GitHub (pinned to 73e0f67d83)