When a call fails

Check the status, then read the shape that goes with it.

Four shapes

Shape You get it for
{"error": {"code": …, "message": …}} A refusal with a name. 404, 422, 502. code is the one thing safe to branch on
{"error": "<message>"} Something not built yet. 501
{"detail": "<message>"} You were stopped before the call got in. 401, 403, 405, 429
{"<field>": ["<reason>"]} Your body or query string could not be read. 400

A 422 about a diagram carries violations as well, listing what is wrong and which block it is about.

The statuses

  • 400 — we could not read what you sent. Keyed by the field at fault, or non_field_errors when no single field is.
  • 401 — no credentials, or credentials that name nobody.
  • 403 — you are signed in and may not do this. Three different things answer this and the body does not say which: your role lacks the permission; the brand is disabled or locked; the subscription has expired and you tried to write.
  • 404 — no such bot, or not yours. The two answer identically. A connected account answers the same way, and one that was revoked, that the app asks to reconnect, or whose credential Google no longer takes, answers as if it were not there. So does a connection: no such connection, or not yours.
  • 405 — the path exists, the method does not.
  • 422 — we understood you and refused. Either a value we do not accept, or a diagram that breaks rules, or a spreadsheet Google will not read through the account you named, or a file we do not keep as media.
  • 429 — too many requests. Every call counts, reads included. Uploading media is also counted per brand, 60 uploads an hour shared by every member.
  • 501 — described here, not built yet.
  • 502 — something we depend on failed. Retrying is reasonable.

Refusals that carry a code

bot_not_found · version_not_found · block_not_found · workspace_not_found · bot_name_not_accepted · channel_family_not_readable · bot_not_in_the_trash · builder_version_not_supported · diagram_beside_a_source · draft_has_violations · restored_draft_has_violations · version_of_an_unsupported_builder · version_is_the_most_recent_publication · diagram_compilation_failed · connected_account_not_found · google_spreadsheets_failed · spreadsheet_not_readable · connection_not_found · media_type_not_accepted · media_too_large

Rules a diagram can break

Each one is a code in a violation. A code you get that is not listed here came from a bot an older builder wrote, and is passed through rather than invented.

Refused on the spot

These answer 422 and store nothing, because there would be nothing sensible to store.

  • block_unknown — the block is of a type we do not describe.
  • block_id_taken — the id you gave a new block already names one in the diagram.
  • block_not_in_draft — you named a block for update or delete that the draft does not hold. Only PATCH /bots/{bot_id}/draft reports it; the single-block endpoints answer 404.
  • block_params_undescribed — the params leave us unable to say which block it is.
  • param_output_id_invalid — something you derive an output from has an id that cannot be one: a button payload not starting with $. Names it in param.
  • param_formula_not_compiled — the formula does not compile.
  • linked_bot_not_found — a bot_link block names by uuid a bot it cannot jump to: not one of the brand's, in the trash, or built with an older builder. Any write can answer it, a whole diagram included, since a uuid is never stored. Names botID in param.
  • connection_output_removed — your change takes away an output a connection still leaves from. Names those connections in connections.
  • connection_block_removed — you added a connection to a block the same change set deletes.

Stored, and reported back

Everything below is saved with your draft. You keep editing; you cannot publish or test until they are gone.

Two of them cut both ways. entry_node_of_another_channel and connection_output_unknown are stored when a whole-diagram write puts them there, and refused on the spot when you add or edit the block that causes them — POST /bots/{bot_id}/draft/blocks is where an id is chosen, and the block-level writes are where an output is.

The block the bot starts from

  • start_connection — the diagram holds neither the greeting node nor the start point.
  • welcome_block_not_allowed — the block in the greeting slot cannot be a greeting. can_be_welcome in GET /blocks says which can.
  • welcome_version_invalid — the greeting does not carry version: 3. landbot bots only. We add the marker when you add the block, so what is left to report is a version you sent yourself, and PUT /bots/{bot_id}/draft, which stores the diagram as it is sent.
  • entry_node_of_another_channel — a node uses another channel family's greeting id: welcome on a bot that is not landbot, or bot_start on one that is. Refused on the spot when you add the block.

Where the bot runs

  • block_not_on_channel — the block does not run on the bot's channel family. channel_restriction in GET /blocks says which families each variant runs on; empty means all of them.

Wiring

  • connection_wrong — a connection has an end the diagram does not contain.
  • connection_output_unknown — a connection leaves from an output its block does not have. Refused on the spot when you add or edit that block.
  • bot_loop — blocks that never wait for an answer form a closed loop, so the conversation never reaches the person.
  • brick_level — bricks nested deeper than allowed.

One param, named in param

  • param_required — missing.
  • param_invalid_type — wrong type.
  • param_no_matching_shape — matches none of the shapes declared for it. GET /blocks has them.
  • param_non_empty — empty where it may not be.
  • param_invalid_format — does not match the pattern in GET /blocks.
  • param_forbidden_format — matches a pattern it must not.
  • param_too_long — longer than max_length.
  • param_not_allowed — not one of the enum values.
  • param_reserved — a value the block keeps for itself.
  • param_unknown_function — a formula calls a function the block does not know.
  • param_invalid_json — has to be JSON and does not parse.
  • connected_account — names an account that is not connected to the bot's brand. Checking it takes a lookup, so it is checked only when you create a bot with a diagram, deploy, publish or restore a version, and never on a draft write: the next write clears it until the next deploy finds it again.
  • connection_bot — a bot_link block names by number a bot that is not one of the brand's, or is in the trash. Names botID in param. Checked when an account is, on the same four paths.
  • connection_wrong on a bot_link block — the bot it jumps to has no published block where the jump enters it. Names nodeID when the block picks one. When it enters at the start, it names botChannelFamily if the target has published the other family's start, so the family written is not the target's; and it names no param if the target has published no greeting at all, as a bot created through this API is born with its greeting slot empty: pick a block, or give the target a greeting and publish it. Checked on the same four paths, against what the target has published, since that is what the conversation reaches.

About storage rather than the diagram

  • block_is_not_valid — a violation was stored against the block with no readable code. Something is wrong with it; what, we cannot recover.