hcengineering/platform · error
update is null
Error message
update is null
What it means
During activity-domain field migration, migrateField computes a new value and, when the value changed, needs the surrounding document update object to write update[field] = newValue. If that update object is null, a programmer/invariant error is thrown because migrations can never apply a change without a target update. This protects against silently dropping migration changes.
Source
Thrown at models/activity/src/migration.ts:306
let newValue: any
if (Array.isArray(oldValue)) {
newValue = []
for (const a of oldValue as any[]) {
const newA = a != null ? await getUpdatedVal(a, au.attrKey) : a
if (newA !== a) {
changed = true
}
newValue.push(newA)
}
} else {
newValue = await getUpdatedVal(oldValue, au.attrKey)
if (newValue !== oldValue) {
changed = true
}
}
if (changed) {
if (update == null) throw new Error('update is null')
update[field] = newValue
}
}
const iterator = await client.traverse(DOMAIN_ACTIVITY, {
_class: activity.class.DocUpdateMessage,
action: 'update',
'attributeUpdates.attrClass': 'core:class:Account'
})
try {
let processed = 0
while (true) {
const docs = await iterator.next(200)
if (docs === null || docs.length === 0) {
break
}View on GitHub (pinned to 63e28dc964)
Solutions
- Ensure migrateAccountsInDocUpdates always passes the current doc's update object into migrateField.
- Add a null check before calling migrateField, skipping docs without an update payload.
- If you call migrateField from custom code, construct or fetch the update object before invoking it.
Example fix
// before
await migrateField(client, doc, field, null, oldValue)
// after
if (update != null) {
await migrateField(client, doc, field, update, oldValue)
} Defensive patterns
Strategy: type-guard
Validate before calling
if (update == null) return // skip docs without an update payload before migrating fields
Type guard
function hasUpdate(u: unknown): u is Record<string, any> {
return u != null && typeof u === 'object'
} Try / catch
try {
await migrateAccountsInDocUpdates(client)
} catch (e) {
if (e.message === 'update is null') {
console.error('doc update payload missing during activity migration; skipping doc')
} else throw e
} Prevention
- Never call migrateField outside the doc-update iteration loop
- Assert update != null in tests for migration code paths
- Keep the update parameter plumbed explicitly, not via optional globals
When it happens
Trigger: migrateAccountsInDocUpdates iterates client.traverse(DOMAIN_ACTIVITY) doc updates and calls migrateField for each field; migrateField is invoked with update=null (or the update was destructured/lost) while the migration actually changes a value (changed=true).
Common situations: Custom migration code that reuses migrateField outside the doc-update loop; traverse returning a doc with no update payload; a refactor renaming the update parameter.
Related errors
- Project ${projectPath} not found
- Teamspace ${teamspacePath} not found
- Document space ${spacePath} not found
- Template meta not found: ${template.id}
- Can only move accounts from mongodb for now
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/f8f549e6e8eef14d.
Report an issue: GitHub.