Select Options

Add, rename, reorder, limit, remap and retire the options of a record-engine select field — the choices behind SELECT_SINGLE and SELECT_MULTI fields and the columns of a board.


Options are the choices of a select field. A SELECT_SINGLE field picks one option per record, a SELECT_MULTI field picks several, and a board grouped by the field renders each option as a column. These mutations manage that option list on record-engine fields — fields defined on a table (database) and mounted on it. For the legacy CustomField option mutations (createCustomFieldOption, editCustomFieldOption, deleteCustomFieldOption), see Single-Select Field and Multi-Select Field; the REST manage-custom-field-options endpoint covers the same legacy rows.

Six mutations cover the whole life cycle:

MutationDoesReturns
createRecordFieldOptionAdd an option (append at the end).optionId, created, position
renameRecordFieldOptionChange title, color, icon, or lock the option.optionId, renamed
moveRecordFieldOptionPlace the option before or after a sibling.Boolean
setRecordFieldOptionWipSet or clear the option’s WIP (work-in-progress) limit.Boolean
remapRecordFieldOptionRetire the option, moving its values onto a target or clearing them.optionId, retired, moved, cleared
remapAndDeleteRecordFieldOptionSame, through a durable, replay-safe write for Blue’s own clients.optionId, deleted, cleared, remappedRecordCount

Every mutation takes workspaceId and scopes to the caller’s workspace; the workspace header selects it, and a mismatch is rejected.

Read options back with the recordFieldOptions query:

query FieldOptions {
  recordFieldOptions(workspaceId: "ws_123", fieldId: "field_123") {
    id
    title
    color
    position
    icon
    isLocked
    wipLimit
    wipLimitHard
  }
}

Create an option

createRecordFieldOption appends one option to a choice field (SELECT_SINGLE or SELECT_MULTI, plus currency and currency-conversion fields, whose options are the allowed currencies and conversion rules). The caller supplies the option id, so repeating a call with the same ids is a no-op that returns created: false instead of adding a duplicate. New options are appended after the existing ones; position is the 0-based ordinal the option landed at.

mutation AddOption {
  createRecordFieldOption(
    input: {
      workspaceId: "ws_123"
      fieldId: "field_123"
      optionId: "option_blocked"
      title: "Blocked"
      color: "#dc3545"
    }
  ) {
    optionId
    created
    position
  }
}
{
  "data": {
    "createRecordFieldOption": { "optionId": "option_blocked", "created": true, "position": 4 }
  }
}

CreateRecordFieldOptionInput

ParameterTypeRequiredDescription
workspaceIdID!YesThe workspace that owns the field.
fieldIdID!YesThe choice field to add the option to.
optionIdID!YesCaller-chosen option id (at most 191 characters). A repeat of an existing id is a no-op.
titleString!YesDisplay text. Must not be blank.
colorString!YesOption color (the app renders hex values; no hex validation).
recordIdIDNoWith databaseId, the record being edited. Enables the delegated path below.
databaseIdIDNoThe table holding that record.

Two authorization paths

  • Schema authority — the workspace OWNER/ADMIN who owns the field, or a user holding the field-management grant, may add options to any of the organization’s choice fields.
  • Delegated (a member adding an option while editing a record) — pass recordId and databaseId. A caller who may edit this field on that record may add an option without schema authority. Without both ids and edit access, the call is refused. The same idempotency and append-at-end rules apply, and no option-count cap applies on either path.

Rename an option

renameRecordFieldOption changes an option’s title, color, icon, or lock state. Stored record values reference the option id, so every record holding the option follows the new label without a rewrite. Send only the properties you want to change; a call that changes nothing returns renamed: false.

isLocked: true locks the option: new records can no longer be created with it (a locked board column refuses quick-add). Existing records keep the option, and moving a record onto it is unaffected. icon is a lowercase lucide-style slug — letters, digits and dashes, at most 64 characters.

Renaming or recoloring also refreshes computed fields that snapshot option labels, and a color change drops board group-color overrides copied from the old color so the explicit new color wins.

mutation RenameOption {
  renameRecordFieldOption(
    input: {
      workspaceId: "ws_123"
      fieldId: "field_123"
      optionId: "option_123"
      title: "In Review"
      color: "#ffc107"
      icon: "eye"
    }
  ) {
    optionId
    renamed
  }
}
{ "data": { "renameRecordFieldOption": { "optionId": "option_123", "renamed": true } } }

RenameRecordFieldOptionInput

ParameterTypeRequiredDescription
workspaceIdID!YesThe workspace that owns the field.
fieldIdID!YesThe field the option belongs to.
optionIdID!YesThe option to change.
titleStringNoNew display text. Must not be blank when sent.
colorStringNoNew color.
iconStringNoOption icon slug; null clears it.
isLockedBooleanNotrue locks the option against new records; false unlocks.

Move an option

moveRecordFieldOption places one option before or after a sibling option of the same field. after: true puts optionId directly after targetOptionId; after: false puts it directly before. Moving an option to where it already is succeeds without change. The order is shared schema — every table mounting the field sees it.

The databaseId must be a table the field is mounted on, in the caller’s workspace.

mutation MoveOption {
  moveRecordFieldOption(
    input: {
      workspaceId: "ws_123"
      databaseId: "db_123"
      fieldId: "field_123"
      optionId: "option_123"
      targetOptionId: "option_456"
      after: true
    }
  )
}
{ "data": { "moveRecordFieldOption": true } }

MoveRecordFieldOptionInput

ParameterTypeRequiredDescription
workspaceIdID!YesThe workspace that owns the field.
databaseIdID!YesA table the field is mounted on.
fieldIdID!YesA SELECT_SINGLE or SELECT_MULTI field.
optionIdID!YesThe option to move.
targetOptionIdID!YesThe sibling to place next to.
afterBoolean!Yestrue places after the sibling, false before it.

Set a WIP limit

A WIP (work-in-progress) limit caps how many records may hold an option — typically a board column. setRecordFieldOptionWip sets that cap on one option of a SELECT_SINGLE field.

The limit is stored on the option, so every table mounting the field sees the same limit, while the count stays local to each table: only that table’s active, non-trashed records count, and a multi-select assignment consumes one slot per table. Two modes:

  • hard: true (BLOCK) — once the count reaches limit, writes that would move a record into the option are refused with WIP_LIMIT_REACHED. Documented exemptions (inbound email, imports) may still exceed the limit.
  • hard: false (WARN) — records may still enter; readers can show that the option is over capacity.

limit: null clears the limit and the blocking behavior.

mutation SetWipLimit {
  setRecordFieldOptionWip(
    input: {
      workspaceId: "ws_123"
      databaseId: "db_123"
      fieldId: "field_123"
      optionId: "option_123"
      limit: 5
      hard: true
    }
  )
}
{ "data": { "setRecordFieldOptionWip": true } }

SetRecordFieldOptionWipInput

ParameterTypeRequiredDescription
workspaceIdID!YesThe workspace that owns the field.
databaseIdID!YesA table the field is mounted on.
fieldIdID!YesA SELECT_SINGLE field.
optionIdID!YesThe option to limit.
limitIntNoMaximum record count. null (or omitted) clears the limit.
hardBoolean!Yestrue blocks writes past the limit; false only warns.

Remap an option (retire it)

remapRecordFieldOption retires an option and says what happens to the values holding it: with targetOptionId, every affected record’s value moves onto that live option of the same field; without one, the values are cleared. Values are never left pointing at a retired option, and a single-select record never ends up holding two options after a merge. History is recorded for every record whose value changes, and dependent computed fields refresh.

The option cannot be remapped onto itself, and the target must be a live option of the same field. Retiring also removes the option from automations that name it.

mutation RemapOption {
  remapRecordFieldOption(
    input: {
      workspaceId: "ws_123"
      fieldId: "field_123"
      optionId: "option_old"
      targetOptionId: "option_new"
    }
  ) {
    optionId
    retired
    moved
    cleared
  }
}
{
  "data": {
    "remapRecordFieldOption": {
      "optionId": "option_old",
      "retired": true,
      "moved": 12,
      "cleared": false
    }
  }
}

RemapRecordFieldOptionInput

ParameterTypeRequiredDescription
workspaceIdID!YesThe workspace that owns the field.
fieldIdID!YesThe field the option belongs to.
optionIdID!YesThe option to retire.
targetOptionIdIDNoA live option of the same field to move values onto. Omit to clear them.

Remap and delete an option

remapAndDeleteRecordFieldOption is the option-delete dialog’s write: it remaps (or clears) exactly like remapRecordFieldOption, then retires the definition — but it runs through a durable transaction and stores its result in a workspace receipt keyed by clientMutationId. A retry after a lost connection returns the original result instead of failing on an already-retired option. Reusing a clientMutationId with a different payload is refused with That client mutation ID was reused. The field must be mounted on a table in the workspace.

The caller must be authenticated. Use a unique clientMutationId per logical delete (a UUID works).

mutation DeleteOption {
  remapAndDeleteRecordFieldOption(
    input: {
      workspaceId: "ws_123"
      fieldId: "field_123"
      optionId: "option_old"
      targetOptionId: "option_new"
      clientMutationId: "0b9e6c1a-2f4e-4a7b-9c3d-1e5f7a9b2c4d"
    }
  ) {
    optionId
    deleted
    cleared
    remappedRecordCount
  }
}
{
  "data": {
    "remapAndDeleteRecordFieldOption": {
      "optionId": "option_old",
      "deleted": true,
      "cleared": false,
      "remappedRecordCount": 12
    }
  }
}

Omit targetOptionId to delete the option and clear its values: cleared comes back true.

RemapAndDeleteRecordFieldOptionInput

ParameterTypeRequiredDescription
workspaceIdID!YesThe workspace that owns the field.
fieldIdID!YesThe field the option belongs to.
optionIdID!YesThe option to delete.
targetOptionIdIDNoA live option of the same field to move every affected record’s value onto. Omit to clear the value instead.
clientMutationIdID!YesCaller-chosen id for replay protection. A retry returns the original result.

Errors

All six return UNAUTHENTICATED when the caller is not signed in and FORBIDDEN when the workspace does not match, the field does not exist in the caller’s organization, or the caller lacks the authority described above.

CodeWhen
BAD_USER_INPUTThe field is not a choice field (“Only choice fields have options.”).
BAD_USER_INPUTThe option is not live on that field (“That option is not available on this field.”).
BAD_USER_INPUTcreateRecordFieldOption: missing or over-long optionId, blank title, or the id already belongs to a different field.
BAD_USER_INPUTrenameRecordFieldOption: blank title or an invalid icon slug.
BAD_USER_INPUTmoveRecordFieldOption / setRecordFieldOptionWip: a missing or over-long id (“Invalid field option scope.”), an unknown option, or a WIP limit that is not a non-negative integer.
BAD_USER_INPUTremapRecordFieldOption / remapAndDeleteRecordFieldOption: the option remapped onto itself, or the target is not a live option of the same field.
BAD_USER_INPUTremapAndDeleteRecordFieldOption: a clientMutationId reused with a different payload.
WIP_LIMIT_REACHEDA later write tried to move a record into an option whose hard WIP limit is full (raised by the value write, not by setRecordFieldOptionWip itself).

Permissions

  • Schema authority — the organization’s OWNER and ADMIN users, the OWNER/ADMIN of the workspace that owns the field, and holders of the field-management grant. setRecordFieldOptionWip, remapRecordFieldOption, and remapAndDeleteRecordFieldOption require it.
  • Field editors — a workspace OWNER/ADMIN, or a MEMBER with edit access to the field in a table they belong to (a custom role needs an EDIT table grant and an editable permission on the field). createRecordFieldOption, renameRecordFieldOption, and moveRecordFieldOption accept field editors in place of schema authority. Viewer-level members never qualify.
  • Delegated create — any caller with edit access to the field on the record named by recordId + databaseId may add an option, no schema authority needed.