Budibase/budibase · error · Error

Relationship Error: Invalid value

Error message

Relationship Error: Invalid value

What it means

`rowSaved` processes link fields after a row save. For each link-type field, the row's value must be an array of link docs (each containing at least an _id). If the field value is non-null but not an array — e.g. a single id string, an object, or a number — the controller cannot compute link diffs and throws 'Relationship Error: Invalid value'.

Source

Thrown at packages/server/src/db/linkedRows/LinkController.ts:184

   * When a row is saved this will carry out the necessary operations to make sure
   * the link has been created/updated.
   * @returns returns the row that has been cleaned and prepared to be written to the DB - links
   * have also been created.
   */
  async rowSaved() {
    const table = await this.table()
    const row = this._row!
    const operations = []
    // get link docs to compare against
    const linkDocs = (await this.getRowLinkDocs(row._id!)) as LinkDocument[]
    for (let fieldName of Object.keys(table.schema)) {
      // get the links this row wants to make
      const rowField = row[fieldName]
      const field = table.schema[fieldName]
      if (field.type === FieldType.LINK && rowField != null) {
        // Expects an array of docs with at least their _id
        if (!Array.isArray(rowField)) {
          throw new Error("Relationship Error: Invalid value")
        }

        // check which links actual pertain to the update in this row
        const thisFieldLinkDocs = linkDocs.filter(
          linkDoc =>
            linkDoc.doc1.fieldName === fieldName ||
            linkDoc.doc2.fieldName === fieldName
        )
        const linkDocIds = thisFieldLinkDocs.map(linkDoc => {
          return linkDoc.doc1.rowId === row._id
            ? linkDoc.doc2.rowId
            : linkDoc.doc1.rowId
        })

        // if 1:N, ensure that this ID is not already attached to another record
        const linkedTable = await this._db.get<Table>(field.tableId)
        const linkedSchema = linkedTable.schema[field.fieldName]

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Wrap the value in an array of ids: field: ["id1", "id2"] instead of field: "id1".
  2. In automations, add a step (JS/script) that normalizes the binding to an array before the row update.
  3. In the builder, bind the link field to the multi-select's array of values, not its raw string.

Example fix

// before
await api.post(`/tables/${tableId}/rows`, { ...row, related: "row_456" })
// after
await api.post(`/tables/${tableId}/rows`, { ...row, related: ["row_456"] })
Defensive patterns

Strategy: type-guard

Validate before calling

const isLinkIds = (v: unknown): boolean =>
  v == null || (Array.isArray(v) && v.every(x => typeof x === "string"))
if (!isLinkIds(row.related)) throw new Error("link fields must be arrays of row ids (or null)")

Type guard

const isLinkIdArray = (v: unknown): v is string[] =>
  Array.isArray(v) && v.every((x): x is string => typeof x === "string")

Try / catch

try {
  await api.post(`/tables/${tableId}/rows`, row)
} catch (err) {
  if (err.message.includes("Relationship Error: Invalid value")) {
    for (const [k, v] of Object.entries(row)) {
      if (linkFields.has(k) && v != null && !Array.isArray(v)) row[k] = [v]
    }
    return api.post(`/tables/${tableId}/rows`, row)
  }
  throw err
}

Prevention

When it happens

Trigger: Saving/updating a row where a link field is set to "row_id_123" (single string) instead of ["row_id_123"], or to an object like {"_id":"x"}, via the REST /rows endpoint, an automation Create/Update Row step, or the builder UI binding a scalar into a multi-select link field.

Common situations: API clients forgetting link fields are arrays; automations passing a query-result string straight into a link field; form components bound to the wrong type producing a single value instead of an array of selected row ids.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/1edc49c7836b8076. Report an issue: GitHub.