linera-io/linera-protocol · error · ExecutionError
StreamNameTooLong
StreamNameTooLong
Error message
ExecutionError::StreamNameTooLong
What it means
ContractRuntime::emit publishes an event on a named stream owned by the calling application. Stream names are raw byte vectors (StreamName(Vec<u8>)) and must be at most MAX_STREAM_NAME_LEN = 64 bytes (linera-execution/src/lib.rs:97). A longer name fails this ensure! deterministically and the transaction aborts; the limit protects stream-index storage, not content size (the event value has its own accounting via track_bytes_written).
Source
Thrown at linera-execution/src/runtime.rs:1438
argument: Vec<u8>,
) -> Result<Vec<u8>, ExecutionError> {
let contract = self
.inner()
.prepare_for_call(self.clone(), authenticated, callee_id)?;
let value = contract
.try_lock()
.expect("Applications should not have reentrant calls")
.execute_operation(argument)?;
self.inner().finish_call();
Ok(value)
}
fn emit(&mut self, stream_name: StreamName, value: Vec<u8>) -> Result<u32, ExecutionError> {
let mut this = self.inner();
ensure!(
stream_name.0.len() <= MAX_STREAM_NAME_LEN,
ExecutionError::StreamNameTooLong
);
let application_id = GenericApplicationId::User(this.current_application().id);
let stream_id = StreamId {
stream_name,
application_id,
};
let value_len = value.len() as u64;
let index = this
.execution_state_sender
.send_request(|callback| ExecutionRequest::Emit {
stream_id,
value,
callback,
})?
.recv_response()?;
// TODO(#365): Consider separate event fee categories.View on GitHub (pinned to 6c226ddcb3)
Solutions
- Shorten the stream name to a fixed, descriptive constant of at most 64 bytes.
- If a long identifier must be part of the name, hash it (e.g. 32-byte hash encoded compactly) and use the hash as the name, or move the identifier into the event value.
- Validate the name at the application's entry point (operation/message decoding) and reject with a clean application error instead of failing mid-execution.
- Add a unit test asserting every stream-name constant used by the app is at most 64 bytes.
Example fix
// before
let name = format!("user-{}-transfers-{}", user_id, description);
let index = runtime.emit(StreamName::from(name.into_bytes()), value)?;
// after
let name = format!("user-{}-txs", user_id); // <= 64 bytes by construction
assert!(name.len() <= 64);
let index = runtime.emit(StreamName::from(name.into_bytes()), value)?; Defensive patterns
Strategy: validation
Validate before calling
const MAX_STREAM_NAME_LEN: usize = 64;
if name.as_bytes().len() > MAX_STREAM_NAME_LEN {
return Err(AppError::StreamNameTooLong); // fail cleanly before emit
}
let index = runtime.emit(StreamName::from(name.as_bytes().to_vec()), value)?; Type guard
fn is_valid_stream_name(name: &str) -> bool {
name.len() <= 64 // byte length, not character count
} Try / catch
match result {
Err(ExecutionError::StreamNameTooLong) => {
// deterministic input error: surface to caller, never retry
}
other => other,
} Prevention
- Define stream names once as constants next to the ABI and reuse them everywhere.
- Count bytes, not characters: multi-byte UTF-8 inflates the length.
- Add a unit test asserting every stream-name constant is at most 64 bytes.
When it happens
Trigger: Calling runtime.emit(stream_name, value) where stream_name is longer than 64 bytes: names built with format!() from user input, names embedding descriptions or long identifiers, or names copied from another system without the length limit.
Common situations: Dynamic stream names constructed from user-supplied strings; multi-byte UTF-8 names that pass a 64-character check in code but exceed 64 bytes on chain; porting an app that used long topic strings; tests with descriptive names that later break on the real runtime.
Related errors
- Checkpoint precondition failed: chain has consumed system ev
- Events not found: {0:?}
- It is illegal to call function process_streams from an opera
- The operation should contain the evm selector and so have le
- BytecodeTooLarge
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/9e7c2425abc844ea.
Report an issue: GitHub.