Errors and recovery¶
Recovery must preserve device identity and avoid turning retries into duplicate commands, corrupt certificates, or partially installed firmware.
Provisioning errors¶
All bindings map RFC 9457 responses to the same taxonomy:
Error code |
HTTP |
Retry |
Action |
|---|---|---|---|
|
400 |
no |
fix request serialization |
|
401 |
no |
restore the correct bootstrap credential or client certificate |
|
403 |
no |
wait for registrar binding or correct model/serial |
|
403 |
never |
quarantine the device and escalate; this is terminal |
|
422 |
no |
regenerate a valid signed CSR |
|
429 |
bounded |
honor |
|
503 |
bounded |
retry with exponential backoff and jitter |
The SDK provisioning clients perform bounded retries for 429 and 503. A surfaced retryable error means their retry budget is exhausted; persist the attempt state and apply a slower outer schedule rather than starting a tight loop.
Python raises typed subclasses of ProvisioningError. Android raises typed
ProvisioningException subclasses. C returns fgai_prov_error_t and provides
last-error accessors. Branch on those types or codes, not localized error text.
Certificate rotation¶
Generate a new key for rotation. Write the new key and certificate to temporary storage, verify that they match and chain to the trusted CA, then atomically switch the active identity. Keep the prior pair until the new pair completes an mTLS proof. If proof fails, restore the prior pair and retry according to the certificate’s remaining validity.
Do not expect rotation to return a new CA chain, MQTT endpoint, or expiry field.
The implemented response contains only thing_id and certificate.
MQTT connection loss¶
Use a stable fgai-<thing_id> client ID, persistent session, one-hour default
session expiry, and exponential reconnect with jitter.
After each reconnect:
re-subscribe commands and SHARED pushes even if the broker reports a resumed session;
restore all message callbacks before application traffic;
republish the complete CLIENT attribute snapshot;
resume telemetry with a monotonic application sequence; and
deduplicate commands by
command_idbefore executing side effects.
Python performs reconnect and re-subscription automatically. C reconnects internally and exposes an informational disconnect callback. The current Android client does not reconnect automatically; the host application must implement the sequence above.
Inbound message failures¶
Reject malformed protobuf messages without applying them. A shared-attribute callback must apply the value durably before acknowledging it. Python currently acknowledges after the callback returns even if the callback raises, so callbacks should contain their own error handling and must not signal success by throwing. Android and C adapters should follow the same explicit effect-then-ack rule.
Command handlers should be short and idempotent. Persist the command ID and operation state before an irreversible side effect. If work is long-running, hand it to a durable local queue and respond according to the command contract; do not block an MQTT network callback.
OTA failures¶
Failure |
Binding signal |
Recovery |
|---|---|---|
HTTP or transport |
Python |
retry safe GET/HEAD with bounded backoff; send feedback when the action supplies a feedback link |
unsafe HAL link |
argument/value failure; C |
reject permanently and report a platform contract error |
SHA-256 mismatch |
Python |
delete the temporary file, report failure, and do not install |
parse failure |
document/JSON exception; C |
retain current firmware and report malformed assignment |
local I/O |
exception; C |
preserve the running slot, reclaim storage, then retry if safe |
Downloads must land in a temporary file or inactive slot. Verify expected size when supplied and SHA-256 before an atomic rename or boot-slot switch. On boot failure, the product bootloader—not DDI—must roll back to the known-good slot.
Licensing failures¶
The device licensing HTTP routes are not published. Treat connection failure or 404 from those compatibility methods as “capability unavailable,” not as a license grant. The Android offline parser is not signature verification and must not be used to fail open. See Device licensing compatibility.
Observability without secret leakage¶
Log operation name, non-secret thing_id, error code, HTTP status, retry count,
and correlation ID. Never log bootstrap or enrollment tokens, JWTs, private
keys, PEM bodies, raw authorization headers, HawkBit upstream credentials, or
command payloads that may contain secrets.