Build a custom machine
Errors
A call the Ownbox will not make raises sdk.BoxRefused. Its .code is the reason, which a rewording never
changes; its message is one sentence saying what to change. Decide in code on .code, never on the words.
try:
r = m.fetch("https://api.example.com/v1/quotes", key="example")
except sdk.BoxRefused as e:
m.save_setting("last_error", e.code) # "host_not_allowed", "key_missing", ...Permissions and money
| Code | Means | Fix |
|---|---|---|
not_permitted | The grant does not cover this call. | Add the line the message names under permissions:. |
host_not_allowed | The host is not under fetch:. | Add the exact host name. |
key_not_allowed | The key is not under keys:. | Add it, with its host and label. |
key_wrong_host | The key belongs to another host. | Fetch its own host, or add a key for this one. |
key_missing | The owner has not entered the key yet. | Link the owner to m.keys_page. |
no_cap | The owner has set no monthly limit for this key. | Link the owner to m.keys_page. |
over_cap | This billing cycle's limit for the key is used. | Wait for the next cycle. |
over_budget | The AI allowance for the month is used. | Catch it where a page must still answer. |
not_on_this_ai | This Ownbox's AI is signed in with ChatGPT, which m.think cannot use yet. | Catch it, as over_budget. |
ai_unavailable | The Ownbox's AI did not answer. | Try again on the next run. |
never_readable | m.secret was called. | Name the key on the request instead. |
Sizes and counts
| Code | Means | Fix |
|---|---|---|
rate_limited | Too many calls or fetches in a minute. | Slow down; try again on the next run. |
too_large | A request, a value, a body or an answer is past its size. | Send less (Limits). |
settings_full | Its settings hold 2 MB already. | Keep large data in m.data_dir(). |
too_many_settings, too_many_jobs, too_many_tools, too_many_kinds, too_many_screens, too_many_panels | Past a count. | Declare fewer. |
Arguments. Each bad_* code names a wrong argument, and the message says which and why: bad_key, bad_idem,
bad_every, bad_name, bad_event, bad_args, bad_title, bad_path, bad_slot, bad_tool, bad_kind,
bad_run, bad_task, bad_prompt, bad_body, bad_headers, bad_url and bad_method.
The web
| Code | Means | Fix |
|---|---|---|
https_only | The address is not https://. | Use https. |
not_public | The host points at a private address. | Use a public host. |
unreachable | The host did not answer in time. | Try again on the next run. |
encoded_answer | The host answered in a form the Ownbox cannot check for the key. | Ask the host for plain JSON or text. |
The door. The SDK handles these itself; a machine sees one only when something is wrong underneath it.
| Code | Means | Fix |
|---|---|---|
sdk_too_new | The machine needs a newer SDK than this Ownbox has. | Wait for the Ownbox's update. |
unknown_call | A call this Ownbox's door does not know. | Check requires.sdk. |
wrong_machine | sdk.machine() names another machine. | Use the folder's own slug. |
unknown_run | An answer for work nobody is waiting on. | None: the work had ended. |
box_error, bad_request, too_many_connections | The door could not take the call. | Try again on the next run. |
Dry runs. dry_run, not_tapped and dry_run_limit are a test holding a call back (Testing). Nothing
to fix, unless the call should have been made: then the owner taps the host.
Answers with a status. The people, conversation and send calls answer their outcome in a dict, and raise only
for what the grant does not allow (not_permitted, and over_cap past the day's count). "unknown" always means it
may have gone: never send it again.
| Call | status | Common code values |
|---|---|---|
m.send_dm, m.reply_to_comment | sent, duplicate, refused, unknown | taken_over, opted_out, box_stopped, window_closed, hourly_cap, not_claimed, too_old, not_ready, unknown_comment |
m.send_email | sent, queued, duplicate, refused, unknown | no_consent, opted_out, unsubscribed, box_stopped, no_person, no_address, bad_draft, failed |
m.notify | sent, skipped, refused | not_a_member, bad_text, off, outside_slot, already_sent, nobody |
m.spend | recorded, duplicate, refused | no_cap, over_cap, not_granted, bad_units, bad_key |
m.propose | waiting, repeat, refused | no_such_kind, bad_kind, bad_title, too_large, too_many_waiting |
sdk.NotYet is raised by a call a custom machine cannot make yet, and sdk.Reserved by a name kept for a later
release; each says, in a sentence, what to use until then.