Skip to content

Errors

Every error response follows the same envelope:

{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description.",
"suggestions": ["optional", "hints"]
}
}

HTTP status codes follow REST conventions: 4xx for client errors, 5xx for server errors.

Error codes

HTTPCodeWhenRetry?
400VALIDATION_ERRORInvalid query parameter (malformed date, bad enum, etc.)No — fix the request
404STATE_NOT_FOUNDUnknown state code / aliasNo — use suggestions
404NOT_FOUNDUnknown routeNo
404HOLIDAY_NOT_FOUNDSpecific ID lookup missedNo
429RATE_LIMITEDExceeded 100 req/minYes, after retryAfter seconds
500INTERNAL_ERRORServer bugYes, with backoff
503SERVICE_UNAVAILABLEData layer offlineYes, with backoff

Examples

Validation

Terminal window
curl "…/v1/holidays/check?date=NOT-A-DATE&state=selangor"
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid date format. Expected YYYY-MM-DD.",
"suggestions": ["2026-03-21"]
}
}

State resolution

Terminal window
curl "…/v1/states/resolve?q=panang"
{
"error": {
"code": "STATE_NOT_FOUND",
"message": "No state matches 'panang'.",
"suggestions": ["pulau-pinang", "pahang"]
}
}

Rate limiting

{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 12s.",
"retryAfter": 12
}
}

The response also carries a Retry-After: 12 header.

SDK error handling

The TypeScript SDK returns a Result envelope instead of throwing, so you handle errors with a simple if check. See SDK Client Usage.