{"record":{"id":"10e3f8f015b062a8","repo":"neondatabase/neon","slug":"unknown-availability-state-s","errorCode":null,"errorMessage":"Unknown availability state '{s}'","messagePattern":"Unknown availability state '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"control_plane/storcon_cli/src/main.rs","lineNumber":409,"sourceCode":"            \"stop\" => Ok(Self(ShardSchedulingPolicy::Stop)),\n            _ => Err(anyhow::anyhow!(\n                \"Unknown scheduling policy '{s}', try active,essential,pause,stop\"\n            )),\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\nstruct NodeAvailabilityArg(NodeAvailabilityWrapper);\n\nimpl FromStr for NodeAvailabilityArg {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        match s {\n            \"active\" => Ok(Self(NodeAvailabilityWrapper::Active)),\n            \"offline\" => Ok(Self(NodeAvailabilityWrapper::Offline)),\n            _ => Err(anyhow::anyhow!(\"Unknown availability state '{s}'\")),\n        }\n    }\n}\n\nasync fn wait_for_scheduling_policy<F>(\n    client: Client,\n    node_id: NodeId,\n    timeout: Duration,\n    f: F,\n) -> anyhow::Result<NodeSchedulingPolicy>\nwhere\n    F: Fn(NodeSchedulingPolicy) -> bool,\n{\n    let waiter = tokio::time::timeout(timeout, async move {\n        loop {\n            let node = client\n                .dispatch::<(), NodeDescribeResponse>(\n                    Method::GET,","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/control_plane/storcon_cli/src/main.rs#L391-L427","documentation":"storcon_cli parses its node-availability CLI argument through a FromStr impl on NodeAvailabilityArg that accepts exactly two lowercase strings: active and offline. Any other input fails during argument parsing, before any request reaches the storage controller. The values map to NodeAvailabilityWrapper::Active and NodeAvailabilityWrapper::Offline.","triggerScenarios":"Running a storcon_cli subcommand that takes an availability flag with a value other than 'active' or 'offline', e.g. 'available', 'down', 'Active', or a scheduling-policy word like 'pause'. Clap reports the anyhow error from NodeAvailabilityArg::from_str.","commonSituations":"Typos or wrong casing; guessing plausible state names ('down', 'unavailable'); confusing availability with scheduling policy (active/essential/pause/stop) and passing the wrong vocabulary to this flag.","solutions":["Re-run with one of the exact lowercase values: active, offline","Run storcon_cli <subcommand> --help to confirm which flag expects availability vs scheduling values","If you meant scheduling behavior, pass active/essential/pause/stop to the scheduling flag instead"],"exampleFix":"# before\nstorcon_cli node configure --node-id 1 --availability down\n# after\nstorcon_cli node configure --node-id 1 --availability offline","handlingStrategy":"validation","validationCode":"fn validate_availability(value: &str) -> Result<(), String> {\n    match value {\n        \"active\" | \"offline\" => Ok(()),\n        _ => Err(format!(\"invalid availability state '{value}', expected 'active' or 'offline'\")),\n    }\n}","typeGuard":"fn is_valid_availability_state(s: &str) -> bool {\n    matches!(s, \"active\" | \"offline\")\n}","tryCatchPattern":null,"preventionTips":["Treat availability (active/offline) and scheduling (active/essential/pause/stop) as separate enums in wrapper code","Add a pre-flight argument check in any automation that drives storcon_cli"],"tags":["cli","argument-parsing","storcon","rust","availability"],"backgroundTag":"invalid-cli-argument","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}