moghtech/komodo · error · anyhow::Error
Invalid container state
Error message
Invalid container state: {} What it means
ContainerStateStatusEnum::from_str converts a Docker-reported container state string into the enum. If the string is not one of running/paused/restarting/removing/exited/dead, it fails with anyhow, embedding the offending string in the message. This guards against unknown or malformed state values coming from Docker.
Solutions
- Log the exact string shown in the error message and compare against the supported set: running, paused, restarting, removing, exited, dead
- Normalize input to lowercase and trim whitespace before calling from_str
- Check Docker Engine version; if it reports a new state, update/patch the Komodo client enum to support it
- Map legacy states like 'created' to a supported variant before parsing
Example fix
// before
let state = ContainerStateStatusEnum::from_str(raw)?;
// after
let state = ContainerStateStatusEnum::from_str(raw.trim().to_lowercase().as_str())
.or_else(|_| match raw.trim().to_lowercase().as_str() {
"created" => Ok(ContainerStateStatusEnum::Exited), // legacy mapping
other => Err(anyhow!("unmapped container state: {other}")),
})?; Defensive patterns
Strategy: validation
Validate before calling
const VALID: [&str; 6] = ["running","paused","restarting","removing","exited","dead"];
fn is_valid_state(s: &str) -> bool { VALID.contains(&s.trim().to_lowercase().as_str()) }
if !is_valid_state(raw) { return Err(anyhow!("unsupported container state: {raw}")); } Type guard
fn is_known_state(s: &str) -> bool {
matches!(s.trim().to_lowercase().as_str(), "running"|"paused"|"restarting"|"removing"|"exited"|"dead")
} Prevention
- Normalize state strings (trim + lowercase) before parsing
- Keep the client's container-state enum in sync with your Docker Engine version
- Treat unknown states as a parse warning, not a crash, in monitoring code
When it happens
Trigger: Deserializing a container state string that is not one of the six known values, e.g. an empty string, whitespace, capitalized text like 'Running', or a state newly introduced by a Docker engine version.
Common situations: Parsing Docker inspect/API responses from a newer Docker Engine that emits a state the client SDK doesn't know; accidentally passing a status (e.g. 'created', 'Up 2 minutes') instead of a state enum string.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
AI-assisted analysis of moghtech/komodo@780ac68b99 (2026-09-08).
Data as JSON: /api/errors/e46e262fe8d18981.
Report an issue: GitHub.
Appendix: source
Thrown at client/core/rs/src/entities/docker/container.rs:344
#[default]
#[serde(rename = "")]
#[strum(serialize = "")]
Empty,
}
impl ::std::str::FromStr for ContainerStateStatusEnum {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"" => Ok(ContainerStateStatusEnum::Empty),
"created" => Ok(ContainerStateStatusEnum::Created),
"running" => Ok(ContainerStateStatusEnum::Running),
"paused" => Ok(ContainerStateStatusEnum::Paused),
"restarting" => Ok(ContainerStateStatusEnum::Restarting),
"removing" => Ok(ContainerStateStatusEnum::Removing),
"exited" => Ok(ContainerStateStatusEnum::Exited),
"dead" => Ok(ContainerStateStatusEnum::Dead),
x => Err(anyhow!("Invalid container state: {}", x)),
}
}
}
/// Health stores information about the container's healthcheck results.
#[typeshare]
#[derive(
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
pub struct ContainerHealth {
/// Status is one of `none`, `starting`, `healthy` or `unhealthy` - \"none\" Indicates there is no healthcheck - \"starting\" Starting indicates that the container is not yet ready - \"healthy\" Healthy indicates that the container is running correctly - \"unhealthy\" Unhealthy indicates that the container has a problem
#[serde(default, rename = "Status")]
pub status: HealthStatusEnum,
/// FailingStreak is the number of consecutive failures
#[serde(rename = "FailingStreak")]
pub failing_streak: Option<I64>,View on GitHub (pinned to 780ac68b99)