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

  1. Shorten the stream name to a fixed, descriptive constant of at most 64 bytes.
  2. 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.
  3. Validate the name at the application's entry point (operation/message decoding) and reject with a clean application error instead of failing mid-execution.
  4. 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

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


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/9e7c2425abc844ea. Report an issue: GitHub.