Errors

Every failure is an RFC 9457 problem document. The code is the stable part — branch on it, never on the prose.

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type": "https://api.goterrago.com/errors/otp_undeliverable",
  "code": "otp_undeliverable",
  "title": "No phone on this account",
  "status": 422,
  "detail": "This account has no phone number, so a sign-in code cannot be sent to it.",
  "request_id": "ceed5aee17b88eaff48b83181e85bb85"
}

request_id is echoed on every response, successful or not. Quote it in a support conversation and the whole request can be found in the logs.

Catalog

Scanned from the call sites that raise them, so a code that is no longer raised is no longer listed. Sites counts how many places in the application raise it — a high count usually means a generic code used across many resources.

CodeTitleStatusSites
account_inactiveThis account is no longer active4013
account_not_allowedDo not name an account4221
account_not_foundNo account to credit this code to4048
account_requiredName the guardian4221
already_set_passwordThis person has already set their password — reset it instead4221
audience_too_largeThe selector matched more than 500 students — narrow it4221
band_has_no_wearerNobody is wearing that band4221
band_has_wearerBand is worn4223
band_reservedBand is reserved for another event4221
band_retiredBand is retired4221
band_type_in_useBand type is in use4091
band_type_name_takenBand type name already used4092
band_unallocatedBand is in the platform stock pool4222
batch_write_forbiddenWrites are not batchable4051
below_withdraw_minimumThat is below the smallest withdrawal we can send4222
cadence_not_availableThat report cannot run on that schedule4221
cannot_remove_yourselfYou cannot remove your own account4221
capacity_exceededThis school has reached its student capacity4222
client_not_foundNo such API client4042
codeTitle4221
code_in_useThat short code belongs to another school4092
conflictCategory save conflict4096
currency_mismatchCurrency does not match the catalog4225
day_requiredChoose which day of the week this digest goes out4222
device_blockedThis device has been blocked4033
device_header_requiredTerra-Device-Fingerprint and Terra-Device-Serial headers are required on this surface4001
device_mismatchToken was not issued to this device4011
device_not_foundDevice not found4044
digest_not_foundDigest not found4043
empty_audienceThe selector matched no students4222
empty_listThere was nothing to read4221
endpoint_inactiveEndpoint is not active4221
event_ambiguousSay which event this top-up is for4221
event_not_heldYou do not hold a ticket to that event4221
exceeds_outstandingRepayment exceeds the outstanding balance4221
export_not_foundExport not found4042
forbiddenInvalid webhook token40322
gateway_unavailableWithdrawals are not available yet5031
group_name_in_useA group with that name already exists4092
group_not_foundSchool group not found4042
guardian_has_no_loginThis parent has no login yet4221
guardian_not_foundGuardian not found4042
guardian_not_linkedThis guardian is not linked to the student4041
home_location_not_foundHome location not found4043
illegal_trip_transitionIllegal trip transition4092
insufficient_fundsPayment refused4229
intelligence_unavailablevaries1
invalid_clientThose client credentials were refused4011
invalid_imageInvalid image4001
invalid_pickup_codeInvalid or expired pickup code4042
invalid_replacement_reasonA replacement is for a lost or damaged band4221
invalid_state_transitionBand is not assignable4227
invalid_tripInvalid trip4221
invalid_zonesvaries2
invite_identity_takenvaries1
invite_invalidThat invitation is not valid any more4101
invite_needs_guardiansAn app invite takes the guardian_ids selector only4221
invoice_not_foundInvoice not found4041
invoice_not_payableInvoice is not payable4221
last_adminThis is the school's only administrator — add another before removing this one4221
link_not_foundLink not found4042
loan_not_activeThe loan is not active4091
log_not_foundService log not found4041
malformed_encodingBody is not valid gzip4001
missing_capabilityYou do not have the capability this action requires4034
ml_unavailableThe optimizer is unavailable right now4042
name_in_useA category with this name already exists4093
no_devicesNone of those devices are yours to move4221
no_open_shiftNo shift is running on this event4041
no_payout_destinationAdd and verify a phone number before withdrawing4091
no_simThe device has no SIM msisdn on record4221
not_a_guardianNot a guardian4032
not_a_platform_operatorOnly a platform operator can view a school in shadow mode.4031
not_enough_stopsNot enough students with a captured home location to suggest a route assignment4042
not_foundUnknown zone40471
not_refundableThis transaction kind cannot be refunded4091
not_shareableNot shareable by this principal4031
not_trip_driverNot the trip driver4035
not_undoableThis event cannot be undone4091
not_your_shiftThis shift belongs to another steward4032
operator_has_no_tenant_scopeA platform operator already sees every school; switching would narrow that.4091
otp_invalidThat code is wrong or has expired4014
otp_undeliverableNo phone on this account4221
overloadedThe service is at its concurrency limit; retry shortlyvaries2
parser_failedThe list could not be read5021
parser_unavailableList reading is switched off5031
payload_not_retainedNothing left to send4221
payload_too_largeCompressed body exceeds 1 MB4132
phone_in_usePhone already registered4094
pin_requiredA PIN is required to set one4221
policy_exceededPolicy exceeded4221
preferences_too_largeThe preference document is too large4221
presence_conflictThe subject is checked in elsewhere4091
profile_in_useUnassign the profile from its wallets first4091
recipient_not_foundThose recipients are not on this school's roster4221
refresh_token_reusedRefresh token reuse detected — session revoked4011
replacement_not_in_stockThe replacement is already issued to somebody4091
role_in_useReassign this role's users first4091
role_name_takenA role with this name already exists4221
role_not_foundUnknown role4042
route_not_foundRoute not found4043
school_not_foundSchool not found4048
school_not_permittedYou do not have access to that school.4031
school_requiredChoose which school this parent belongs to.4221
serial_in_useSerial already registered4092
session_already_closedUndo the check-out first4091
session_revokedThis session has ended — sign in again4011
settings_not_foundNotification settings not found4041
setup_incompleteSchool setup is not finished4221
shadow_session_cannot_switchLeave shadow mode before switching schools.4091
shift_closedThis shift has already been closed4091
sku_in_useAn item with this SKU already exists4092
spending_profile_emptyThat profile sets no limits4221
stale_versionThe row moved since you read it — refetch, re-apply, retry40914
student_not_foundStudent not found40412
survey_not_activeSurvey is not active4091
survey_not_draftSurvey is not a draft4091
template_not_foundTemplate not found (platform templates are read-only here)4041
template_provider_failedWhatsApp template provider refused5021
tenant_not_permittedYou do not have access to that school.4032
tenant_requiredName the organizer this event belongs to4225
ticket_already_claimedThis seat already has a real holder4091
ticket_already_redeemedSomebody has already walked in on this ticket4091
ticket_not_transferableOnly an issued ticket can change hands4221
ticketing_invalid_keyvaries1
ticketing_not_connectedNo ticketing integration is connected4044
ticketing_sync_failedvaries1
ticketing_webhook_failedvaries1
trip_not_foundTrip not found40414
trip_not_replayableA trip can only be replayed after it ends4093
trip_plan_not_foundTrip plan not found4041
trip_replay_emptyThis trip synced no GPS points4041
trip_route_comparison_unavailableNot enough data to compare this trip to an optimal plan4041
trip_route_segments_unavailableNot enough data to build a segment-by-segment comparison for this trip4041
unauthenticatedInvalid credentials4015
undo_window_elapsedThe undo window has elapsed4221
unknown_bandUnknown band4047
unknown_band_typeUnknown band type4045
unknown_beneficiaryUnknown beneficiary4221
unknown_categoryUnknown category4222
unknown_eventEvent not found on that organizer4041
unknown_gatewayUnknown payment gateway4222
unknown_organizerUnknown organizer4042
unknown_replacement_bandThe replacement serial is not registered here4041
unknown_reportThat report cannot be scheduled4221
unknown_roleThe role does not exist in this tenant4221
unknown_schoolSchool not found4046
unknown_spending_profileUnknown spending profile4221
unknown_stopOne or more stops do not belong to this plan's route4221
unknown_studentOne or more students do not exist in this tenant4221
unknown_templateUnknown template4222
unknown_wallet_typeUnknown wallet type4223
unknown_zoneZone not found in this tenant4223
unsupported_encodingOnly Content-Encoding: gzip is supported on this endpoint4151
user_has_no_emailThis person has no email address — add one before inviting them4221
user_not_foundUser not found4046
validation_failedstudents must name 1–42222
vehicle_capacity_missingNo buses have a seat capacity on file — set capacities before suggesting a route assignment4221
vehicle_fields_requiredCapacity, fuel type, and fuel consumption are required when adding a new bus4221
vehicle_on_tripVehicle already on a trip4091
voucher_invalidVoucher invalid4221
voucher_redeemedVoucher already redeemed4092
voucher_unfundedVoucher cannot be honored4221
wallet_has_balanceRefund or transfer the wallet balance before removing this learner4221
wallet_has_transactionsThis learner has spending history — close the wallet before removing them4221
wallet_not_foundWallet not found40417
wallet_unavailableThis event cannot take top-ups yet4092
wallet_unresolvableNo wallet could be derived for the wearer4222
wallet_wearer_mismatchWallet does not belong to the wearer4221
zone_not_assignedThis zone is not assigned to you4031
zone_not_foundZone not found4044
zone_requiredName the gate — this school has more than one4221