hcengineering/platform · error

invalid relation key ${key.key}

Error message

invalid relation key ${key.key}

What it means

getRelationPresenter resolves association-based relation keys (containing $associations). The key must contain a dot-separated path; if the key has no '.' it cannot encode an association and the function throws immediately.

Source

Thrown at plugins/view-resources/src/utils.ts:639

          key: '',
          sortingKey: '',
          presenter: ErrorPresenter,
          label: stringKey as IntlString,
          _class: core.class.TypeString,
          props: { error: err },
          collectionAttr: false,
          isLookup: false
        }
        return errorPresenter
      }
    })
  return (await Promise.all(model)).filter((a) => a !== undefined)
}

async function getRelationPresenter (client: Client, key: BuildModelKey): Promise<AttributeModel> {
  const parts = key.key.split('.')
  if (parts.length < 2) {
    throw new Error('invalid relation key ' + key.key)
  }

  // Find the last association segment
  let lastAssocIndex = -1
  for (let i = 0; i < parts.length; i++) {
    if (parts[i] === '$associations' && i + 1 < parts.length) {
      lastAssocIndex = i
    }
  }
  if (lastAssocIndex === -1) {
    throw new Error('invalid relation key ' + key.key)
  }

  const fragments = parts[lastAssocIndex + 1].split('_')
  const assocId = fragments[0] as Ref<Association>
  const assoc = client.getModel().findObject(assocId)
  if (assoc === undefined) {
    throw new Error('association not found for ' + assocId)

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Use a full relation key of the form 'path.$associations.assocId_x', e.g. 'spaces.$associations.space_a'
  2. Verify the key string contains at least one '.' before passing to model()
  3. Split logic: only route keys containing '$associations' to relation presenter

Example fix

// before
{ key: '$associations' }
// after
{ key: 'spaces.$associations.<assocId>_a' }
Defensive patterns

Strategy: validation

Validate before calling

function isValidRelationKey(key: string): boolean {
  return key.includes('.') && key.includes('$associations')
}
if (!isValidRelationKey(key)) throw new Error('bad relation key: ' + key)

Try / catch

try {
  return await model(client, _class, [{ key }])
} catch (err) {
  if (String(err.message).startsWith('invalid relation key')) {
    console.warn('malformed relation key, skipping:', key)
    return []
  }
  throw err
}

Prevention

When it happens

Trigger: Passing a BuildModelKey to model()/getPresenter whose key contains '$associations' but has no dot, e.g. key: '$associations' or key: 'myKey' routed to relation presenter.

Common situations: Hand-written view key strings missing the dotted path; copy-pasted keys from another view with different structure; typos that drop the association id segment.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/34fb26e572b6deda. Report an issue: GitHub.