hcengineering/platform · warning

TxApplyIf failed

Error message

TxApplyIf failed

What it means

TxApplyIf evaluates match/notMatch measure scopes and only applies the wrapped transactions when the condition passes. When the condition does not pass, the server logs this warning with the scope, failure reason, measure names, and match/notMatch/tx counts. It is not an exception — the transactions are simply skipped.

Source

Thrown at foundations/server/packages/middleware/src/applyTx.ts:66

        // Wait for scope promise if found
        const passed =
          applyIf.scope != null ? await this.verifyApplyIf(ctx, applyIf) : { passed: true, onEnd: () => {} }
        try {
          if (passed.passed) {
            const applyResult: TxApplyResult = {
              success: true,
              serverTime: 0
            }
            result.push(applyResult)

            const st = Date.now()
            const r = await this.provideTx(ctx, applyIf.txes)
            if (Object.keys(r).length > 0) {
              result.push(r)
            }
            applyResult.serverTime = Date.now() - st
          } else {
            ctx.warn('TxApplyIf failed', {
              scope: applyIf.scope,
              reason: passed.reason,
              measureName: applyIf.measureName,
              matchCount: applyIf.match?.length ?? 0,
              notMatchCount: applyIf.notMatch?.length ?? 0,
              txCount: applyIf.txes.length
            })
            result.push({
              success: false
            })
          }
        } finally {
          passed.onEnd()
        }
      } else {
        part.push(tx)
      }
    }

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Inspect the logged reason/scope/measureName to see which condition failed
  2. Verify the measure names and scope ids in the applyIf operation match actual model definitions
  3. Check current measure values (matchCount/notMatchCount) to confirm expected state before sending the conditional tx
  4. Split the operation: query first, then send plain tx only when the condition truly holds

Example fix

// before
await client.applyTx(ctx, { txes, applyIf: { scope, measureName: 'members', txes } })
// after — verify measure state first
const res = await client.findAll(ctx, space, query)
if (res.length === expected) {
  await client.tx(ctx, txes)
}
Defensive patterns

Strategy: type-guard

Validate before calling

const measureRes = await client.findAll(ctx, targetClass, measureQuery)
if (measureRes.length !== expectedCount) {
  console.warn('applyIf condition would fail; measure state:', measureRes.length)
}

Type guard

function txWillPass(passed: { reason?: string } | true): passed is true {
  return passed === true
}

Try / catch

const result = await client.applyTx(ctx, ops)
if (result.some(r => Object.keys(r).length > 0)) {
  console.warn('applyIf condition failed; tx skipped', result)
  // re-check state and retry with corrected measures
}

Prevention

When it happens

Trigger: Calling applyTx (or txIf) with an ApplyIf operation whose measure conditions (match/notMatch against the given scope) evaluate to false, with the reason field explaining which check failed.

Common situations: Client logic building conditional transactions with wrong measure names; counters already at the expected value so match arrays don't align; measure data not yet committed by a prior op; typos in scope or measure ids.

Related errors


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