Skip to content

Errors & exceptions

The error taxonomy is how your component tells which subsystem failed — config, schema validation, messaging, credentials, parameters, or streaming — and decides whether to recover or abort. Each SDK exposes the same set of failure modes, but in its own idiomatic shape, so the type you catch differs by language even when the underlying cause is identical.

There is no single, unified error type across the four languages. Only Rust unifies everything into one enum; TypeScript unifies the core subsystems only; Java and Python use a distinct exception class per subsystem.

A small set of subsystem exceptions in com.mbreissi.edgecommons. Some are checked (the compiler forces a try/catch or throws), some are unchecked (RuntimeException).

// package com.mbreissi.edgecommons.*
class ConfigurationException extends Exception // CHECKED — config.ConfigurationException
class ConfigurationValidator.ConfigurationValidationException // CHECKED — nested static in config.ConfigurationValidator
extends Exception
class CredentialException extends RuntimeException // unchecked — credentials.CredentialException
class ParameterException extends RuntimeException // unchecked — parameters.ParameterException
class EdgeStreamException extends RuntimeException { // unchecked — streaming.EdgeStreamException
EdgeStreamException(int code, String message);
int code(); // the underlying esl_status value
// constants mirroring esl_status:
// OK=0, ERR_CONFIG=1, ERR_IO=2, ERR_CORRUPT=3, ERR_FULL=4,
// ERR_UNKNOWN_STREAM=5, ERR_SINK=6, ERR_PANIC=7, ERR_INVALID_ARG=8
}

CLI and builder preconditions throw the standard IllegalArgumentException (e.g. unknown --platform / --transport, the unsupported -m/--mode flag) and IllegalStateException (builder precondition violations).

The same logical failure maps to a different type in each SDK. Read across a row to translate.

Subsystem failure Java Python Rust TypeScript
CLI / arg validation IllegalArgumentException ValueError EdgeCommonsError::Cli EdgeCommonsError kind "Cli"
Config load ConfigurationException (checked) ValueError / propagated EdgeCommonsError::Config EdgeCommonsError kind "Config"
Schema validation ConfigurationValidationException (checked) ConfigurationValidationException EdgeCommonsError::Validation EdgeCommonsError kind "Validation"
Messaging standard exception (no dedicated class) standard exception (no dedicated class) EdgeCommonsError::Messaging EdgeCommonsError kind "Messaging"
Metrics standard exception (no dedicated class) standard exception (no dedicated class) EdgeCommonsError::Metrics EdgeCommonsError kind "Metrics"
Greengrass IPC standard exception (no dedicated class) standard exception (no dedicated class) EdgeCommonsError::Ipc EdgeCommonsError kind "Ipc"
UNS topic build/validate UnsValidationException (+getCode()) UnsValidationError (+.code) EdgeCommonsError::UnsValidation { code, .. } UnsValidationError (+.code)
Reserved-class publish ReservedTopicException ReservedTopicError EdgeCommonsError::ReservedTopic ReservedTopicError
Request deadline java.util.concurrent.TimeoutException (exceptional future) RequestTimeoutError (raised by Iou.get()) EdgeCommonsError::RequestTimeout RequestTimeoutError (rejected promise)
Credentials CredentialException CredentialError EdgeCommonsError::Credentials CredentialError
Parameters ParameterException ParameterError EdgeCommonsError::Parameters ParameterError
Streaming EdgeStreamException (+code()) EdgeStreamError (+.code) EdgeCommonsError::Streaming (code discarded) EdgeStreamError (+.code)
I/O · JSON JDK IOException etc. stdlib exceptions EdgeCommonsError::Io / EdgeCommonsError::Json EdgeCommonsError kind "Io" / "Json"

The UNS validation errors carry the machine-readable code set pinned in uns-test-vectors/ (EMPTY_TOKEN, BAD_CHAR, DEPTH_EXCEEDED, … — see the UNS API reference), identical across languages.

  • ConfigurationException — thrown by ConfigManagerFactory.create(...) when no configuration is found, or when a ConfigManager cannot be created. It is not thrown by ConfigManager itself.
  • ConfigurationValidationException — thrown by ConfigurationValidator.validate(JsonObject) when the config violates the canonical JSON schema. It is fail-closed: a missing schema resource on the classpath also throws (it does not silently pass).
  • CredentialException — vault open/decrypt failures: a wrong KEK, tampered data, an unsupported vault format, or corrupt JSON. Messages never include secret or key material.
  • ParameterException — parameter resolution/decryption failures (the parameters subsystem reuses the credentials vault as an encrypted cache).
  • EdgeStreamException — any non-zero esl_status from the native edgestreamlog engine; inspect code() (e.g. ERR_UNKNOWN_STREAM, ERR_CONFIG, ERR_FULL) to branch.

Streaming is the one place that carries a numeric status (esl_status from the native edgestreamlog engine) — but only three of the four SDKs preserve it.

EdgeStreamException.code() returns the int, and named constants are exposed (EdgeStreamException.ERR_FULL, ERR_UNKNOWN_STREAM, …) so you can branch on a name.

EdgeStreamException ex = assertThrows(EdgeStreamException.class, () -> svc.stats("nope"));
assertEquals(EdgeStreamException.ERR_UNKNOWN_STREAM, ex.code()); // 5

Optional subsystems return empty, they do not throw

Section titled “Optional subsystems return empty, they do not throw”

Credentials, parameters, and streaming are opt-in: when the matching config section is absent (and, in Rust, the matching cargo feature is enabled), the accessor returns an empty value rather than throwing. Always check before use.

getStreams(), getCredentials(), and getParameters() return null when the section is absent. getMessaging() and getMetrics() return the wired subsystem.

var creds = gg.getCredentials();
if (creds == null) {
// no `credentials` config section — feature is off
} else {
var secret = creds.get("db-password");
}

A minimal, idiomatic handler in each language — catch the validation error to abort startup, and branch on the streaming status code where it is available.

import com.mbreissi.edgecommons.config.ConfigurationValidator;
import com.mbreissi.edgecommons.config.ConfigurationValidator.ConfigurationValidationException;
import com.mbreissi.edgecommons.streaming.EdgeStreamException;
// Checked: the compiler forces you to handle (or declare) this one.
try {
ConfigurationValidator.validate(config); // JsonObject
} catch (ConfigurationValidationException e) {
log.error("config rejected: {}", e.getMessage()); // lists each schema violation
throw new IllegalStateException("cannot start", e); // abort startup
}
// Unchecked, code-bearing.
try {
var stats = gg.getStreams().stats("telemetry");
} catch (EdgeStreamException e) {
if (e.code() == EdgeStreamException.ERR_FULL) {
// durable buffer is full — back off and retry later
} else {
throw e;
}
}

Whether a failure (or shutdown) ends the OS process differs sharply across the SDKs. This matters when a supervisor (the Nucleus, a container runtime, Kubernetes) watches the exit code.