Hmbown/CodeWhale · error
invalid persisted user image content kind
Error message
invalid persisted user image content kind
What it means
Thrown by `validate_stored_image_content` in crates/tui/src/image_attach.rs when a persisted user message intended to carry images contains a ContentBlock that is neither Text nor ImageUrl. Only these two block kinds are legal for stored image input; any other variant makes the persisted record invalid. This protects the reload path from deserializing unexpected block shapes into runtime requests.
Solutions
- Remove or convert the unsupported content block so only Text and ImageUrl blocks remain
- Regenerate/rewrite the persisted record with the current schema before validating
- If a new block kind must be allowed, update the matches! pattern in validate_stored_image_content explicitly
Example fix
// before: invalid block kind in stored image message
let blocks = vec![ContentBlock::Text{..}, ContentBlock::ToolUse{..}];
// after: only Text/ImageUrl blocks permitted
let blocks = vec![ContentBlock::Text{..}, ContentBlock::ImageUrl{..}]; Defensive patterns
Strategy: validation
Validate before calling
fn only_text_or_image(blocks: &[ContentBlock]) -> bool {
blocks.iter().all(|b| matches!(b, ContentBlock::Text{..} | ContentBlock::ImageUrl{..}))
} Type guard
fn is_image_input_block(b: &ContentBlock) -> bool {
matches!(b, ContentBlock::Text { .. } | ContentBlock::ImageUrl { .. })
} Try / catch
match validate_stored_image_content(blocks) {
Ok(()) => /* proceed */,
Err(e) if e.to_string().contains("invalid persisted user image content kind") => /* rewrite or migrate the stored record */,
Err(e) => return Err(e),
} Prevention
- Only persist Text and ImageUrl blocks into user image messages
- Version persisted session records and migrate on schema changes
- Never hand-edit session JSON without validating block kinds afterwards
When it happens
Trigger: Calling `validate_stored_image_content` with a blocks slice containing any ContentBlock variant other than Text or ImageUrl (e.g. ToolUse, ToolResult, or a newer block type added after the record was written).
Common situations: Persisted session files written by a newer/older Codewhale version with different block kinds; hand-edited or migrated session JSON; a bug that stored tool blocks into a user image message.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid version 1 pet bucket.
- persisted image input must contain an image
- Runtime Chat binding state uses an unsupported schema
- Codewhale terminal receipt contained a non-scalar field
- Duplicate .
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/f5e6812a19ff39a2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/image_attach.rs:199
mime: mime.to_string(),
data_base64: data.to_string(),
});
}
}
prepare_stored_images(&images)?;
Ok(images)
}
/// Validate new image-bearing durable records without rewriting their block order.
/// Legacy schema 2 history continues to use its original interpretation.
pub(crate) fn validate_stored_image_content(blocks: &[ContentBlock]) -> Result<()> {
if blocks.iter().any(|block| {
!matches!(
block,
ContentBlock::Text { .. } | ContentBlock::ImageUrl { .. }
)
}) {
bail!("invalid persisted user image content kind");
}
if runtime_images_from_blocks(blocks)?.is_empty() {
bail!("persisted image input must contain an image");
}
Ok(())
}
/// Why a file could not be attached as an image.
///
/// Every variant renders to a sentence naming the file and the reason. These
/// strings reach both the user (as a command error) and the model (as an
/// in-band notice), so they say what to do next rather than only what failed.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ImageAttachError {
/// The file could not be read at all.
Unreadable { path: String, reason: String },
/// The file is zero bytes.
Empty { path: String },View on GitHub (pinned to 73e0f67d83)