Success and failure shape
Chameleon’s REST-style flows generally return:
type ChameleonAPIResult<T> =
| { ok: true, data: T }
| { ok: false, error: string, message: string, status: number, code?: number, raw?: unknown }
Why this exists
The framework prefers explicit branching over exception-driven control flow:
- success stays local to
result.data
- failure carries HTTP status and API details
- raw error payloads can still be inspected when needed
- scripts and service-style processes can stay predictable without
try/catch around every request
Example
const result = await client.channels.fetch(channelId)
if (!result.ok) {
console.error(result.error)
console.error(result.status)
console.error(result.raw)
return
}
console.log(result.data.name)
When the framework still throws
Some higher-level interaction helpers can still throw when Discord rejects an already-constructed payload, especially in acknowledgement paths such as showModal(...).
That is usually a payload-construction problem, not a contradiction of the result model. Manager and REST flows still follow ChameleonAPIResult<T>; direct interaction acknowledgement helpers may need to throw immediately because Discord accepts only one response path for that interaction.Last modified on June 13, 2026