{"record":{"id":"865615e63c3d0785","repo":"astrid-runtime/astrid","slug":"native-provider-returned-an-invalid-structured-err","errorCode":null,"errorMessage":"native provider returned an invalid structured error","messagePattern":"native provider returned an invalid structured error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/storage.rs","lineNumber":327,"sourceCode":"        }) => println!(\n            \"mount {mount_id} at {}: {access:?}, dirty={dirty}\",\n            mountpoint.display()\n        ),\n        StorageProviderOutcomeV1::Success(StorageProviderSuccessV1::Unmounted { mount_id }) => {\n            println!(\"unmounted {mount_id}\");\n        },\n        StorageProviderOutcomeV1::Failure(failure) => {\n            if failure.code.is_empty()\n                || failure.code.len() > 64\n                || !failure\n                    .code\n                    .bytes()\n                    .all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-')\n                || failure.message.is_empty()\n                || failure.message.len() > 4096\n                || failure.message.chars().any(char::is_control)\n            {\n                bail!(\"native provider returned an invalid structured error\");\n            }\n            eprintln!(\n                \"storage provider error [{}]: {}\",\n                failure.code, failure.message\n            );\n            return Ok(ExitCode::FAILURE);\n        },\n    }\n    Ok(ExitCode::SUCCESS)\n}\n\nfn platform_provider_name() -> &'static str {\n    #[cfg(target_os = \"macos\")]\n    {\n        \"astrid-storage-provider-fskit\"\n    }\n    #[cfg(target_os = \"linux\")]\n    {","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/storage.rs#L309-L345","documentation":"When a native provider returns a Failure outcome, render_response validates the structured error: the code must be lowercase ASCII letters/digits/hyphens and the message must be non-empty, at most 4096 bytes, and free of control characters. If any check fails, the CLI cannot safely render the provider's error and bails with this generic message.","triggerScenarios":"A provider Failure outcome has a code containing uppercase/underscore/space characters, or an empty/oversize (>4096 bytes) message, or a message containing control characters (e.g. embedded newline in provider JSON output) — validated in render_response, exercised by the fskit_gap/newline/oversize tests.","commonSituations":"Provider emits raw OS error strings containing newlines or terminal control codes; provider uses CamelCase or snake_case error codes instead of kebab-case; provider serializes a multi-MB log blob as the failure message; provider returns empty message when it has no detail.","solutions":["Fix the provider to emit kebab-case error codes ([a-z0-9-]) and sanitize messages (strip control chars, truncate to 4096 bytes)","Ensure the provider replaces newlines in error messages (e.g. with spaces) before serializing JSON","Provide a meaningful non-empty fallback message when no detail is available","Log the raw provider output separately if you control both sides, so invalid payloads can be diagnosed"],"exampleFix":"// before (provider)\nmessage: format!(\"failed: \\n{raw_os_error_output}\"),\n// after\nlet msg: String = raw_os_error_output.chars().filter(|c| !c.is_control()).take(4096).collect();\nmessage: if msg.is_empty() { \"unknown provider failure\".into() } else { msg },","handlingStrategy":"validation","validationCode":"fn structured_error_ok(code: &str, msg: &str) -> bool { code.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-') && !msg.is_empty() && msg.len() <= 4096 && !msg.chars().any(char::is_control) }","typeGuard":"fn sane_failure(f: &StorageProviderFailureV1) -> Option<&StorageProviderFailureV1> { if structured_error_ok(&f.code, &f.message) { Some(f) } else { None } }","tryCatchPattern":"match sane_failure(&failure) {\n    Some(f) => eprintln!(\"storage provider error [{}]: {}\", f.code, f.message),\n    None => eprintln!(\"provider returned an unrenderable structured error\"),\n}","preventionTips":["Use a kebab-case code generator/enum in the provider","Strip control characters and truncate messages to 4096 bytes on the provider side","Never log raw OS error blobs directly into structured error messages"],"tags":["ipc","error-rendering","input-validation"],"backgroundTag":"invalid-json-response","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}