{"record":{"id":"3fc91bb101f8e35a","repo":"moeru-ai/airi","slug":"expectation-failed-expectnear-target-requires-la","errorCode":null,"errorMessage":"Expectation failed: expectNear(target) requires last action result with endPos telemetry","messagePattern":"Expectation failed: expectNear\\(target\\) requires last action result with endPos telemetry","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"integrations/minecraft/src/cognitive/conscious/js-planner.ts","lineNumber":1280,"sourceCode":"  if (targetOrMaxDist && typeof targetOrMaxDist === 'object' && typeof targetOrMaxDist.x === 'number' && typeof targetOrMaxDist.y === 'number' && typeof targetOrMaxDist.z === 'number') {\n    target = { x: targetOrMaxDist.x, y: targetOrMaxDist.y, z: targetOrMaxDist.z }\n    if (typeof maxDistOrMessage === 'number')\n      maxDist = maxDistOrMessage\n    if (typeof maybeMessage === 'string')\n      message = maybeMessage\n  }\n  else {\n    if (typeof targetOrMaxDist === 'number')\n      maxDist = targetOrMaxDist\n    if (typeof maxDistOrMessage === 'string')\n      message = maxDistOrMessage\n  }\n\n  let distance = null\n  if (target) {\n    const endPos = globalThis.lastAction?.result?.endPos\n    if (!endPos || typeof endPos.x !== 'number' || typeof endPos.y !== 'number' || typeof endPos.z !== 'number') {\n      throw new Error('Expectation failed: expectNear(target) requires last action result with endPos telemetry')\n    }\n\n    const dx = endPos.x - target.x\n    const dy = endPos.y - target.y\n    const dz = endPos.z - target.z\n    distance = Math.sqrt(dx * dx + dy * dy + dz * dz)\n  }\n  else if (typeof globalThis.lastAction?.result?.distanceToTargetAfter === 'number') {\n    distance = globalThis.lastAction.result.distanceToTargetAfter\n  }\n\n  if (distance === null) {\n    throw new Error('Expectation failed: expectNear() requires target argument or last action distanceToTargetAfter telemetry')\n  }\n\n  if (distance <= maxDist)\n    return true\n","sourceCodeStart":1262,"sourceCodeEnd":1298,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/integrations/minecraft/src/cognitive/conscious/js-planner.ts#L1262-L1298","documentation":"Inside globalThis.expectNear(target, ...), when a target coordinate object {x,y,z} is supplied, the helper computes Euclidean distance from globalThis.lastAction.result.endPos to the target. If endPos is absent or not a full numeric {x,y,z}, it cannot compute distance and throws this message. The expectation is that movement actions report an endPos telemetry field; without it the proximity check is impossible.","triggerScenarios":"Calling expectNear({x,y,z}) after an action whose result does not include endPos (e.g. after chat, craft, or a movement action that did not populate endPos); calling expectNear with a target before any action has run this turn (lastAction is null); the action result schema dropped the endPos field after a refactor.","commonSituations":"First assertion in a script with no preceding movement action; using expectNear against a non-movement action; telemetry field renamed from endPos to something else; the action returns a partial result on early failure without endPos.","solutions":["Call a movement action that reports endPos before expectNear(target).","Verify via log() that globalThis.lastAction.result has the expected endPos shape.","If you only need proximity to a known target, prefer the no-target overload that uses distanceToTargetAfter telemetry if available.","Ensure the movement action's result schema includes numeric endPos {x,y,z}."],"exampleFix":"// before\n//   await chat({ message: 'hi' })\n//   expectNear({ x: 10, y: 64, z: -5 })  // throws: no endPos from chat\n//\n// after\n//   await use('moveTo', { x: 10, y: 64, z: -5 })\n//   expectNear({ x: 10, y: 64, z: -5 }, 2)","handlingStrategy":"validation","validationCode":"// Before expectNear(target), confirm endPos telemetry exists:\n// const end = globalThis.lastAction?.result?.endPos\n// if (end && typeof end.x === 'number' && typeof end.y === 'number' && typeof end.z === 'number') {\n//   expectNear(target, maxDist)\n// } else {\n//   log('expectNear skipped: no endPos telemetry')\n// }","typeGuard":"function hasEndPos(r: unknown): r is { endPos: { x: number, y: number, z: number } } {\n  const e = (r as any)?.endPos\n  return !!e && typeof e.x === 'number' && typeof e.y === 'number' && typeof e.z === 'number'\n}","tryCatchPattern":null,"preventionTips":["Always run a movement action that reports endPos before expectNear(target).","Log lastAction.result to learn which telemetry fields the action provides.","Prefer the no-target overload when only distanceToTargetAfter is available.","Confirm the action's result schema includes a numeric endPos {x,y,z}."],"tags":["llm-planner","sandbox","assertion","expectnear","telemetry"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}