linera-io/linera-protocol · error
Invalid stream ID: {s}
Error message
Invalid stream ID: {s} What it means
StreamId::from_str splits the string on the LAST colon (rsplit_once): the left part must parse as a GenericApplicationId ('System' or 'User:<id>'), the right part as a StreamName (hex bytes). If there is no colon at all, this error is raised; a colon present but malformed parts surfaces the chained 'Invalid GenericApplicationId!'/'Invalid StreamName!' errors instead.
Source
Thrown at linera-base/src/identifiers.rs:707
Display::fmt(&self.stream_name, f)
}
}
impl std::str::FromStr for StreamId {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts = s.rsplit_once(":");
if let Some((part0, part1)) = parts {
let application_id =
GenericApplicationId::from_str(part0).context("Invalid GenericApplicationId!")?;
let stream_name = StreamName::from_str(part1).context("Invalid StreamName!")?;
Ok(StreamId {
application_id,
stream_name,
})
} else {
Err(anyhow!("Invalid stream ID: {s}"))
}
}
}
/// An event identifier.
#[derive(
Debug,
PartialEq,
Eq,
Hash,
Clone,
Serialize,
Deserialize,
WitLoad,
WitStore,
WitType,
SimpleObject,
Allocative,View on GitHub (pinned to 6c226ddcb3)
Solutions
- Use the full Display form '<application-id>:<stream-name-hex>', e.g. 'User:e40c...:a1b2'
- Stream names are hex-encoded bytes (StreamName::from_str uses hex::decode), so keep them valid hex
- Round-trip through StreamId::to_string() rather than manual formatting
Example fix
// before: bare stream name, no colon
let id: StreamId = stream_name_hex.parse()?; // Err: Invalid stream ID
// after: application id + ':' + hex stream name
let id: StreamId = format!("System:{stream_name_hex}").parse()?; Defensive patterns
Strategy: type-guard
Validate before calling
fn looks_like_stream_id(s: &str) -> bool {
let Some((app, name)) = s.rsplit_once(':') else { return false };
(app == "System" || app.starts_with("User:"))
&& !name.is_empty()
&& name.bytes().all(|b| b.is_ascii_hexdigit())
} Type guard
fn parse_stream_id(s: &str) -> Option<StreamId> {
s.parse().ok()
} Prevention
- Require the full '<application-id>:<hex-stream-name>' form in configs and APIs
- Stream names are hex; reject non-hex early at input boundaries
- Round-trip through StreamId::to_string() instead of manual formatting
When it happens
Trigger: Calling parse::<StreamId>() on a string with no ':' at all, e.g. a bare stream name like 'a1b2c3' or an application ID alone. Valid shapes are 'System:a1b2' and 'User:e40c...:a1b2'.
Common situations: Config or query parameters that carry only the stream name; copying the StreamName component instead of the full StreamId; truncation when the hex stream name is dropped.
Related errors
- Invalid blob ID: {s}
- Invalid parsing of GenericApplicationId
- Invalid address value: {s}
- Failed to obtain a port
- GITHUB_PR_NUMBER is not a valid number: {pr_string}
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/3f39fa164ac7abb6.
Report an issue: GitHub.