Skip to content

Absence Reason Enum

Enumerated taxonomy — instantiates First-Class Absence Modeling

Attaches a machine-readable code to an empty result naming why it is empty, so consumers can branch on no-match versus denied versus not-yet-loaded.

An Absence Reason Enum is a closed, machine-readable set of codes attached to an empty result that names why it is empty — NO_MATCH, NOT_ENROLLED, ACCESS_DENIED, REDACTED, NOT_YET_LOADED, UPSTREAM_ERROR. Its defining idea is that it encodes the cause of absence as data a machine can switch on, so a consumer branches on why there is nothing rather than merely noticing that there is nothing. This is the machine-side counterpart to Empty-State Message: the enum is the code a service switches on, while the message is the human copy that code may later be rendered into.

Example

An identity-verification service exposes a lookup that returns a person's record. Today it returns none. Without a reason code, the calling application cannot tell three very different situations apart: the person is genuinely not enrolled; the caller lacks permission to view them; or the upstream identity provider timed out. All three arrive as the same empty result, and the caller either guesses or treats them identically — which is how a permissions failure gets logged as "user not found." With an Absence Reason Enum, the response carries { result: [], reason: NOT_ENROLLED }, or ACCESS_DENIED, or UPSTREAM_TIMEOUT. The consuming service now routes each correctly: NOT_ENROLLED to an onboarding flow, ACCESS_DENIED to an audit log, UPSTREAM_TIMEOUT to a retry with backoff. One empty shape yields three correct behaviors. It is the same discipline HTTP encodes when it distinguishes 204 No Content from 404 Not Found from 403 Forbidden.[1]

How it works

  • A closed enum in the contract. The reason codes live in the schema or API contract as a fixed, versioned set, one code per distinct cause of absence.
  • Carried alongside the empty payload. The code travels with the (empty) result, so a consumer reads nothing here and here is why together.
  • Consumers switch on the cause. Downstream logic branches on the code — retry, escalate, offer onboarding, surface a message — instead of treating all emptiness alike.
  • Logged for the record. Because the code is discrete, it can be counted and audited, making patterns of absence (a spike in UPSTREAM_TIMEOUT) visible.

Tuning parameters

  • Granularity — a few coarse codes versus many fine ones. Coarse is easy to handle exhaustively; fine gives precise routing but more cases for every consumer to cover.
  • Open vs. closed enum — whether to reserve an OTHER/UNKNOWN catch-all. A catch-all keeps old consumers from breaking when a code is added, but it also becomes a place real causes hide.
  • Severity mapping — whether each code carries or implies a severity/escalation level, so the propagation policy can key off it.
  • Contract stability — treating the code set as a versioned interface, since adding a code can break consumers that assumed exhaustive handling.

When it helps, and when it misleads

Its strength is collapsing the archetype's most dangerous confusion — that empty, denied, not-yet-loaded, and failed all look alike — into a single discrete, auditable signal. Consumers stop guessing, and absence becomes countable.

Its failure mode is code drift: teams add reasons that old consumers do not handle, so a fresh cause falls into a default branch and is silently swallowed — or worse, a wrong code is emitted, and an ACCESS_DENIED mislabeled as NO_MATCH both misinforms the caller and can leak whether a record exists. A catch-all UNKNOWN that accumulates real causes is the same failure in slow motion. The guarding discipline is to treat the enum as a versioned contract, require exhaustive handling at consumers, and keep sensitive causes honest — never folding a denial into a no-match to simplify the code.

How it implements the components

  • absence_reason_code — the enum is the reason-code taxonomy: a discrete, machine-readable cause attached to each empty result.
  • nonvalue_distinction_map — its codes are precisely the map that keeps empty, denied, not-loaded, and error from collapsing into one another.
  • empty_case_observability — because each cause is a discrete, loggable code, absence becomes visible and countable in logs and audit trails.

It does not produce human-facing copy or a next-step action for the person looking at the screen — user_facing_empty_state_message, fallback_or_creation_path — that is Empty-State Message, which consumes these codes and renders them for people.

Editorial Notes

Form Classification

Form family: Representation, Specification & Plan

Rationale: The mechanism attaches a machine-readable code to an empty result naming why it is empty, so consumers can branch on no-match versus denied versus not-yet-loaded, so its operative form is a static or prospective information artifact.

Independent corroboration: The frozen evidence defines Absence Reason Enum as 'Attaches a machine-readable code to an empty result naming why it is empty, so consumers can branch on no-match versus denied versus not-yet-loaded', so its operative form is Representation, Specification & Plan.

Review outcome: Independent reviewer agreement; medium confidence.

Origin Attribution

Primary origin: Computer Science & Software Engineering

Origin pattern: Single lineage

Present-day reach: Specialized

Rationale: Closed enums, typed API contracts, exhaustive branching, status codes, and machine-readable error semantics are characteristic software-engineering and programming-language mechanisms.

Review outcome: Independent reviewer agreement; high confidence.

References

[1] Fielding, Roy T., Mark Nottingham, and Julian Reschke. HTTP Semantics. RFC 9110 (2022). Defines distinct semantics for 204 No Content, 403 Forbidden, and 404 Not Found rather than collapsing those absence conditions. registry ↩