pw_status#
pw_status provides features for communicating the result of an operation.
The classes in pw_status are used extensively throughout Pigweed.
Status#
The primary feature of pw_status is the Status class (in C++) or enum
(in other languages). pw_status provides an implementation of status in
every supported Pigweed language.
The C++ implementation is pw::Status, a simple, zero-overhead
status object that wraps a status code. Other languages use an enum.
Pigweed’s status uses Google’s standard status codes (see the Google APIs repository). These codes are used extensively in Google projects including Abseil (status/status.h) and gRPC (doc/statuscodes.md).
Status codes#
-
enumerator OK = 0#
OKdoes not indicate an error; this value is returned on success. It is typical to check for this value before proceeding on any given call across an API or RPC boundary. To check this value, use theok()member function rather than inspecting the raw code.C++
pw::OkStatus()C
PW_STATUS_OKPython / Java / TypeScript
Status.OKRust
Ok(val)
-
enumerator CANCELLED = 1#
CANCELLEDindicates the operation was cancelled, typically by the caller.C++
pw::Status::Cancelled()C
PW_STATUS_CANCELLEDPython / Java / TypeScript
Status.CANCELLEDRust
Error::Cancelled
-
enumerator UNKNOWN = 2#
UNKNOWNindicates an unknown error occurred. In general, more specific errors should be raised, if possible. Errors raised by APIs that do not return enough error information may be converted to this error.C++
pw::Status::Unknown()C
PW_STATUS_UNKNOWNPython / Java / TypeScript
Status.UNKNOWNRust
Error::Unknown
-
enumerator INVALID_ARGUMENT = 3#
INVALID_ARGUMENTindicates the caller specified an invalid argument, such as a malformed filename. Note that use of such errors should be narrowly limited to indicate the invalid nature of the arguments themselves. Errors with validly formed arguments that may cause errors with the state of the receiving system should be denoted withFAILED_PRECONDITIONinstead.C++
pw::Status::InvalidArgument()C
PW_STATUS_INVALID_ARGUMENTPython / Java / TypeScript
Status.INVALID_ARGUMENTRust
Error::InvalidArgument
-
enumerator DEADLINE_EXCEEDED = 4#
DEADLINE_EXCEEDEDindicates a deadline expired before the operation could complete. For operations that may change state within a system, this error may be returned even if the operation has completed successfully. For example, a successful response from a server could have been delayed long enough for the deadline to expire.C++
pw::Status::DeadlineExceeded()C
PW_STATUS_DEADLINE_EXCEEDEDPython / Java / TypeScript
Status.DEADLINE_EXCEEDEDRust
Error::DeadlineExceeded
-
enumerator NOT_FOUND = 5#
NOT_FOUNDindicates some requested entity (such as a file or directory) was not found.NOT_FOUNDis useful if a request should be denied for an entire class of users, such as during a gradual feature rollout or undocumented allowlist. If a request should be denied for specific sets of users, such as through user-based access control, usePERMISSION_DENIEDinstead.C++
pw::Status::NotFound()C
PW_STATUS_NOT_FOUNDPython / Java / TypeScript
Status.NOT_FOUNDRust
Error::NotFound
-
enumerator ALREADY_EXISTS = 6#
ALREADY_EXISTSindicates that the entity a caller attempted to create (such as a file or directory) is already present.C++
pw::Status::AlreadyExists()C
PW_STATUS_ALREADY_EXISTSPython / Java / TypeScript
Status.ALREADY_EXISTSRust
Error::AlreadyExists
-
enumerator PERMISSION_DENIED = 7#
PERMISSION_DENIEDindicates that the caller does not have permission to execute the specified operation. Note that this error is different than an error due to an unauthenticated user. This error code does not imply the request is valid or the requested entity exists or satisfies any other pre-conditions.PERMISSION_DENIEDmust not be used for rejections caused by exhausting some resource. Instead, useRESOURCE_EXHAUSTEDfor those errors.PERMISSION_DENIEDmust not be used if the caller cannot be identified. Instead, useUNAUTHENTICATEDfor those errors.C++
pw::Status::PermissionDenied()C
PW_STATUS_PERMISSION_DENIEDPython / Java / TypeScript
Status.PERMISSION_DENIEDRust
Error::PermissionDenied
-
enumerator RESOURCE_EXHAUSTED = 8#
RESOURCE_EXHAUSTEDindicates some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space.C++
pw::Status::ResourceExhausted()C
PW_STATUS_RESOURCE_EXHAUSTEDPython / Java / TypeScript
Status.RESOURCE_EXHAUSTEDRust
Error::ResourceExhausted
-
enumerator FAILED_PRECONDITION = 9#
FAILED_PRECONDITIONindicates that the operation was rejected because the system is not in a state required for the operation’s execution. For example, a directory to be deleted may be non-empty, anrmdiroperation is applied to a non-directory, etc.Some guidelines that may help a service implementer in deciding between
FAILED_PRECONDITION,ABORTED, andUNAVAILABLE:Use
UNAVAILABLEif the client can retry just the failing call.Use
ABORTEDif the client should retry at a higher transaction level (such as when a client-specified test-and-set fails, indicating the client should restart a read-modify-write sequence).Use
FAILED_PRECONDITIONif the client should not retry until the system state has been explicitly fixed. For example, if armdirfails because the directory is non-empty,FAILED_PRECONDITIONshould be returned since the client should not retry unless the files are deleted from the directory.
C++
pw::Status::FailedPrecondition()C
PW_STATUS_FAILED_PRECONDITIONPython / Java / TypeScript
Status.FAILED_PRECONDITIONRust
Error::FailedPrecondition
-
enumerator ABORTED = 10#
ABORTEDindicates the operation was aborted, typically due to a concurrency issue such as a sequencer check failure or a failed transaction.See the guidelines above for deciding between
FAILED_PRECONDITION,ABORTED, andUNAVAILABLE.C++
pw::Status::Aborted()C
PW_STATUS_ABORTEDPython / Java / TypeScript
Status.ABORTEDRust
Error::Aborted
-
enumerator OUT_OF_RANGE = 11#
OUT_OF_RANGEindicates the operation was attempted past the valid range, such as seeking or reading past an end-of-file.Unlike
INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state changes. For example, a 32-bit file system will generateINVALID_ARGUMENTif asked to read at an offset that is not in the range [0,2^32-1], but it will generateOUT_OF_RANGEif asked to read from an offset past the current file size.There is a fair bit of overlap between
FAILED_PRECONDITIONandOUT_OF_RANGE. We recommend usingOUT_OF_RANGE(the more specific error) when it applies so that callers who are iterating through a space can easily look for anOUT_OF_RANGEerror to detect when they are done.C++
pw::Status::OutOfRange()C
PW_STATUS_OUT_OF_RANGEPython / Java / TypeScript
Status.OUT_OF_RANGERust
Error::OutOfRange
-
enumerator UNIMPLEMENTED = 12#
UNIMPLEMENTEDindicates the operation is not implemented or supported in this service. In this case, the operation should not be re-attempted.C++
pw::Status::Unimplemented()C
PW_STATUS_UNIMPLEMENTEDPython / Java / TypeScript
Status.UNIMPLEMENTEDRust
Error::Unimplemented
-
enumerator INTERNAL = 13#
INTERNALindicates an internal error has occurred and some invariants expected by the underlying system have not been satisfied. This error code is reserved for serious errors.C++
pw::Status::Internal()C
PW_STATUS_INTERNALPython / Java / TypeScript
Status.INTERNALRust
Error::Internal
-
enumerator UNAVAILABLE = 14#
UNAVAILABLEindicates the service is currently unavailable and that this is most likely a transient condition. An error such as this can be corrected by retrying with a backoff scheme. Note that it is not always safe to retry non-idempotent operations.See the guidelines above for deciding between
FAILED_PRECONDITION,ABORTED, andUNAVAILABLE.C++
pw::Status::Unavailable()C
PW_STATUS_UNAVAILABLEPython / Java / TypeScript
Status.UNAVAILABLERust
Error::Unavailable
-
enumerator DATA_LOSS = 15#
DATA_LOSSindicates that unrecoverable data loss or corruption has occurred. As this error is serious, proper alerting should be attached to errors such as this.C++
pw::Status::DataLoss()C
PW_STATUS_DATA_LOSSPython / Java / TypeScript
Status.DATA_LOSSRust
Error::DataLoss
-
enumerator UNAUTHENTICATED = 16#
UNAUTHENTICATEDindicates that the request does not have valid authentication credentials for the operation. Correct the authentication and try again.C++
pw::Status::Unauthenticated()C
PW_STATUS_UNAUTHENTICATEDPython / Java / TypeScript
Status.UNAUTHENTICATEDRust
Error::Unauthenticated
C++ API#
-
class Status#
Statusis a thin, zero-cost abstraction around thepw_Statusenum. It initializes toOKby default and addsok()andstr()methods. Implicit conversions are permitted betweenpw_Statusandpw::Status.An
OKStatusis created by thepw::OkStatus()function or by the defaultStatusconstructor. Non-OKStatusis created with a static member function that corresponds with the status code.Public Functions
-
inline constexpr bool ok() const#
True if the status is
OK.This function is provided in place of an
IsOk()function.
-
inline constexpr void Update(Status other)#
Updates this
Statusto the providedStatusIF this status isOK. This is useful for tracking the first encountered error, as calls to this helper will not change one error status to another error status.
-
inline constexpr void IgnoreError() const#
Ignores any errors. This method does nothing except potentially suppress complaints from any tools that are checking that errors are not dropped on the floor.
-
inline constexpr bool ok() const#
-
constexpr Status pw::OkStatus()#
Returns an
OKstatus. Equivalent toStatus()orStatus(PW_STATUS_OK). This function is used instead of aStatus::Ok()function, which would be too similar toStatus::ok().
-
enum pw_Status#
Enum to use in place of
pw::Statusin C code. Always usepw::Statusin C++ code.The values of the
pw_Statusenum are all-caps and prefixed withPW_STATUS_. For example,PW_STATUS_DATA_LOSScorresponds withDATA_LOSS.
Tracking the first error encountered#
Pigweed AI summary: This article discusses the usefulness of tracking the first error encountered while allowing execution to continue. Manually writing out if statements to check and assign can become verbose and doesn't explicitly highlight the intended behavior of "latching" to the first error. The article provides a code example using the pw::Status::Update() helper function to reduce visual clutter and succinctly highlight the intended behavior.
In some contexts it is useful to track the first error encountered while
allowing execution to continue. Manually writing out if statements to check
and then assign quickly becomes verbose, and doesn’t explicitly highlight the
intended behavior of “latching” to the first error.
Status overall_status;
for (Sector& sector : sectors) {
Status erase_status = sector.Erase();
if (!overall_status.ok()) {
overall_status = erase_status;
}
if (erase_status.ok()) {
Status header_write_status = sector.WriteHeader();
if (!overall_status.ok()) {
overall_status = header_write_status;
}
}
}
return overall_status;
pw::Status has a pw::Status::Update() helper function
that does exactly this to reduce visual clutter and succinctly highlight the
intended behavior.
Status overall_status;
for (Sector& sector : sectors) {
Status erase_status = sector.Erase();
overall_status.Update(erase_status);
if (erase_status.ok()) {
overall_status.Update(sector.WriteHeader());
}
}
return overall_status;
Unused result warnings#
Pigweed AI summary: This paragraph discusses the "Unused result warnings" feature in Pigweed. If the PW_STATUS_CFG_CHECK_IF_USED option is enabled, the returned pw::Status objects must be used, or else it will result in a compilation error. To silence these warnings, IgnoreError() can be called on the returned status object. This option is disabled by default, but Pigweed compiles with it enabled. Projects using Pigweed will need to update to compile with this option, and eventually, unused result warnings will
If the PW_STATUS_CFG_CHECK_IF_USED option is enabled, pw::Status objects
returned from function calls must be used or it is a compilation error. To
silence these warnings call IgnoreError() on the returned status object.
PW_STATUS_CFG_CHECK_IF_USED defaults to off. Pigweed compiles with this
option enabled, but projects that use Pigweed will need to be updated to compile
with this option. After all projects have migrated, unused result warnings will
be enabled unconditionally.
C compatibility#
Pigweed AI summary: The pw_status function provides a C-compatible enum for status codes, which can be converted to and from the pw::Status class. However, the pw_Status enum should not be used in C++, and instead the pw::Status class should be used.
pw_status provides the C-compatible pw_Status enum for the status
codes. For ease of use, pw::Status implicitly converts to and from
pw_Status. However, the pw_Status enum should never be used
in C++; instead use the pw::Status class.
Rust API#
Pigweed AI summary: The Rust API for pw_status is documented in the rustdoc API docs.
pw_status’s Rust API is documented in our
rustdoc API docs.
StatusWithSize#
Pigweed AI summary: The pw::StatusWithSize class is a useful way to report a status and an unsigned integer value. It is similar to the pw::Result<T> class, but it stores both a size and a status, regardless of the status value, and only supports a limited range of 27 bits. Values can be created using functions similar to pw::Status. Examples include creating an OK StatusWithSize with a size of 123, a NOT_FOUND StatusWithSize with a size of 0,
pw::StatusWithSize (pw_status/status_with_size.h) is a convenient,
efficient class for reporting a status along with an unsigned integer value.
It is similar to the pw::Result<T> class, but it stores both a size and a
status, regardless of the status value, and only supports a limited range (27
bits).
pw::StatusWithSize values may be created with functions similar to
pw::Status. For example,
// An OK StatusWithSize with a size of 123. StatusWithSize(123) // A NOT_FOUND StatusWithSize with a size of 0. StatusWithSize::NotFound() // A RESOURCE_EXHAUSTED StatusWithSize with a size of 10. StatusWithSize::ResourceExhausted(10)
PW_TRY#
Pigweed AI summary: PW_TRY is a set of macros that simplify working with Status and StatusWithSize objects in functions that return them. The macros call a function and return early if the function's return status is not ok. PW_TRY_ASSIGN is similar but also assigns the size from the StatusWithSize object on ok. To enable pw_status for Zephyr, add CONFIG_PIGWEED_STATUS=y to the project's configuration.
PW_TRY (pw_status/try.h) is a convenient set of macros for working
with Status and StatusWithSize objects in functions that return Status or
StatusWithSize. The PW_TRY and PW_TRY_WITH_SIZE macros call a
function and do an early return if the function’s return status is not ok.
Example:
Status PwTryExample() {
PW_TRY(FunctionThatReturnsStatus());
PW_TRY(FunctionThatReturnsStatusWithSize());
// Do something, only executed if both functions above return OK.
}
StatusWithSize PwTryWithSizeExample() {
PW_TRY_WITH_SIZE(FunctionThatReturnsStatus());
PW_TRY_WITH_SIZE(FunctionThatReturnsStatusWithSize());
// Do something, only executed if both functions above return OK.
}
PW_TRY_ASSIGN is for working with StatusWithSize objects in in functions
that return Status. It is similar to PW_TRY with the addition of assigning
the size from the StatusWithSize on ok.
Status PwTryAssignExample() {
size_t size_value
PW_TRY_ASSIGN(size_value, FunctionThatReturnsStatusWithSize());
// Do something that uses size_value. size_value is only assigned and this
// following code executed if the PW_TRY_ASSIGN function above returns OK.
}
Zephyr#
Pigweed AI summary: To enable pw_status for Zephyr, add CONFIG_PIGWEED_STATUS=y to the project's configuration.
To enable pw_status for Zephyr add CONFIG_PIGWEED_STATUS=y to the
project’s configuration.