Stream Errors and Diagnostics
The stream API separates bounded flow-control results from exceptional I/O and encoding failures.
This page shows how to branch on normal results, inspect StreamError, render diagnostics, retain source context, and
handle malformed text separately.
Separate Results from Failures
Timeout and Finished are result states.
Timeout gives control back to the caller without changing the stream into Failed; finished marks normal input
completion.
Native read, write, flush, close, or positioning failures throw
StreamError.
/// Keep timeout, end-of-stream, and failure on separate control-flow paths.
/// Timeout is a bounded result, `Finished` is a successful end state, and a stream failure throws `StreamError`.
void distinguishResultStates() {
auto input = ScriptedByteInputStream{{7U}, 1U, 1U};
el::io::printLine("Tiempo agotado: "_el, input.readByte().isTimeout());
el::io::printLine("Dato marino: "_el, input.readByte().hasData());
el::io::printLine("Fin normal: "_el, input.readByte().isFinished());
}
Tiempo agotado: true
Dato marino: true
Fin normal: true
Inspect Structured Context
StreamError contains StreamErrorContext.
Its title states what failed; its description explains why.
Optional help suggests recovery, path identifies a file-backed source, and platform context carries native details
without nesting a second cause.
/// `StreamError` carries a structured, user-facing context.
/// Handlers can inspect its title, description, recovery help, path, and optional native platform context.
void inspectStreamError() {
auto input = ScriptedByteInputStream{{1U}};
input.setFailure(true);
try {
static_cast<void>(input.readByte());
} catch (const el::StreamError &error) {
el::io::printLine("Title: "_el, error.title());
el::io::printLine("Description: "_el, error.description());
el::io::printLine("Estado Failed: "_el, input.state() == el::StreamState::Failed);
}
}
Title: Failed to read the scripted stream.
Description: The simulated sensor source failed.
Estado Failed: true
Report the Common Diagnostic
Use diagnostic() or DiagnosticHelper to transform the exception into
the same renderer-neutral document used by application errors.
This keeps terminal output, logs, and graphical reporting consistent.
/// Convert a stream exception into the common diagnostic document used by logs and user interfaces.
/// This avoids constructing a second message and preserves the original stream-domain context.
void reportDiagnostic() {
auto output = ScriptedByteOutputStream{};
output.setFailure(true);
try {
output.flush();
} catch (const el::StreamError &error) {
const auto document = el::DiagnosticHelper{error}.toDocument();
el::io::printLine(document.toString());
}
}
Error: Failed to flush the scripted stream.
The simulated recorder failed.
Preserve Context Through Wrappers
Text encoders, temporary streams, and standard proxies delegate context creation to the backing stream’s
StreamErrorSource before adding their own context data.
The final exception therefore retains a useful file path and native details even when failure was detected at a
decorated text operation.
/// Encoded and temporary stream wrappers forward locally created errors to their backing stream.
/// As a result, a text-level operation can still report the path associated with its file-backed byte source.
void preserveWrappedContext() {
const auto directory = createStreamDemoDirectory("océano"_el);
const auto path = directory->path() / "arrecife.txt"_el;
const auto output = path.content().openTextOutputStream();
output->write("coral"_el);
output->close();
try {
static_cast<void>(output->write("pez"_el));
} catch (const el::StreamError &error) {
el::io::printLine("Ruta conservada: "_el, error.path().endsWith("arrecife.txt"_el));
}
}
Ruta conservada: true
Handle Encoding Errors Separately
Strict decoding throws EncodingError because malformed text is not a native
stream failure.
Catch it separately when the application can explain invalid input differently from an unavailable file or device.
/// Encoding failures are text-domain errors rather than stream failures.
/// Configure strict decoding when malformed marine-observation text must be rejected and handle `EncodingError`
/// separately from native I/O failures.
void handleEncodingError() {
const auto directory = createStreamDemoDirectory("codificación"_el);
const auto path = directory->path() / "muestra.txt"_el;
path.content().writeDataOrThrow(el::ByteBlock({0xf0U, 0x28U, 0x8cU, 0x28U}));
auto options = el::PathReadTextOptions{el::StringEncoding::Utf8};
options.setEncodingMode(el::EncodingMode::Strict);
try {
static_cast<void>(path.content().openTextInputStream(options)->readAll());
} catch (const el::EncodingError &) {
el::io::printLine("The malformed UTF-8 sequence was rejected."_el);
}
}
The malformed UTF-8 sequence was rejected.
After a stream enters Failed, report its original error and replace the stream only at an application-level recovery
boundary.
Do not retry arbitrary requests on the failed instance.