diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:35:12 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:35:12 -0300 |
| commit | 2ed1190f0f021bc4de17b47d8d4ed7241611d6f1 (patch) | |
| tree | 221a8ba542c35ec66b4c79805067749e78c5e03f /README.md | |
| parent | ae9ad8a4c61b793f6859c84dac80b1c1b04b7b68 (diff) | |
| download | lisp-ca6b7cd072afbb85d2331d396882ea52afc3a20c.tar.gz | |
A CEP that fails is rarely random: it is someone who knows the city and
guessed the number, most often the -000 that 957 municipalities never
received. The API now answers that 404 with the municipality owning the
band the CEP falls in, and without it every caller can say no more than
"does not exist" to a person who is one digit away from the right CEP.
It lands on the condition rather than in a return value because it is
context for the failure and nothing else: the answer is still a 404, and
a faixa must never read as an address that resolved. Parsing it is
deliberately defensive for the same reason — a missing, malformed or
empty block yields NIL, so a field that only adds context cannot turn a
clean not-found into a parse failure, and an older API stays supported.
The ends of the band are the CEPs that actually exist, not the bounds
the Correios publish, and the band is sparse; the docstrings and the
README say so, because presenting the pair as a range of valid CEPs is
the mistake this data invites.
models is compiled before errors so the report function can name the
faixa's municipality.
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 39 |
1 files changed, 39 insertions, 0 deletions
@@ -191,6 +191,45 @@ status that caused it: `error-message` returns the description of any of them; `server-error-status` and `rate-limited-retry-after` carry the extra facts their callers need. +### The municipality behind a CEP that does not exist + +A CEP that fails is rarely random. It is usually someone who knows the city and +guessed the number — and the classic guess is the `-000` that 957 +municipalities never received. So `cep-not-found` carries a `faixa`: the +municipality that owns the band the CEP falls in, when the API knows one. + +```lisp +(handler-case (cepis:lookup "25845000") + (cepis:cep-not-found (e) + (let ((faixa (cepis:cep-not-found-faixa e))) + (if faixa + (format nil "This CEP does not exist. Did you mean somewhere in ~a/~a?" + (cepis:faixa-localidade faixa) ; "Areal" + (cepis:faixa-uf faixa)) ; "RJ" + "This CEP does not exist.")))) +``` + +The rest of the fields are `faixa-estado`, `faixa-regiao`, `faixa-ibge`, +`faixa-cep-ini`, `faixa-cep-fim` and `faixa-ceps`. + +Three things about it, all of which are easy to get wrong: + +- **It is still a 404.** The condition is signalled exactly as before; the + `faixa` is context for the error, not an address. A municipality here never + means the CEP resolved. +- **`cep-ini` and `cep-fim` are the CEPs that actually exist**, the smallest + and the largest in the DNE for that municipality — not the bounds the + Correios publish. Areal's official start is `25845000`, which is precisely + the CEP that just failed; `faixa-cep-ini` is `25845001`. +- **The band is sparse.** Areal's 118 CEPs are scattered over the ~4,900 + numbers between its two ends, and `faixa-ceps` is there to say so. Never + present the pair as a range of valid CEPs. + +`cep-not-found-faixa` is `nil` when the CEP falls in a band no municipality +owns — the API omits the field, it never sends null — and also when the body +cannot be read. A malformed `faixa` never turns a clean not-found into an +`invalid-response`. + `invalid-cep` is also a `parse-error` and `cep-not-found` a `cell-error`, so code already handling those standard types during input validation keeps working without knowing this library exists — and `cell-error-name` gives back |