{"record":{"id":"cbc67b39485dc2ea","repo":"moeru-ai/airi","slug":"expectation-failed-expected-moveddistance-th","errorCode":null,"errorMessage":"Expectation failed: Expected movedDistance >= ${threshold}, got ${movedDistance}","messagePattern":"Expectation failed: Expected movedDistance >= (.+?), got (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"integrations/minecraft/src/cognitive/conscious/js-planner.ts","lineNumber":1252,"sourceCode":"  const actionName = globalThis.lastAction?.action?.tool\n  const nonMovingActions = [\n    'chat', 'giveUp', 'skip', 'stop', 'followPlayer', 'clearFollowTarget',\n    'givePlayer', 'consume', 'equip', 'putInChest', 'takeFromChest', 'discard',\n    'collectBlocks', 'mineBlockAt', 'craftRecipe', 'smeltItem', 'clearFurnace',\n    'placeHere', 'attack', 'attackPlayer', 'activate', 'recipePlan',\n  ]\n\n  if (!globalThis.lastAction || (typeof actionName === 'string' && nonMovingActions.includes(actionName)))\n    return true\n\n  const movedDistance = typeof globalThis.lastAction?.result?.movedDistance === 'number'\n    ? globalThis.lastAction.result.movedDistance\n    : 0\n\n  if (movedDistance >= threshold)\n    return true\n\n  throw new Error(\n    'Expectation failed: ' + __plannerExpectationDetail(message, 'Expected movedDistance >= ' + threshold + ', got ' + movedDistance),\n  )\n}\n\nglobalThis.expectNear = (targetOrMaxDist, maxDistOrMessage, maybeMessage) => {\n  let target = null\n  let maxDist = 2\n  let message\n\n  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')","sourceCodeStart":1234,"sourceCodeEnd":1270,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/integrations/minecraft/src/cognitive/conscious/js-planner.ts#L1234-L1270","documentation":"globalThis.expectMoved(minBlocks, message) asserts that the most recent movement-bearing action actually displaced the bot by at least `threshold` blocks (default 0.5). It reads globalThis.lastAction.result.movedDistance. A whitelist of non-moving actions (chat, skip, craftRecipe, mineBlockAt, etc.) short-circuits to true because they are not expected to move the bot. For movement actions, if movedDistance is missing or below the threshold, it throws with the actual and expected values.","triggerScenarios":"Calling expectMoved() after a moveTo/navigate action that pathfinder could not complete (movedDistance 0 or <0.5); the action result object omitted a numeric movedDistance field; the bot was already at the goal so net displacement was under threshold; a movement action was blocked by terrain and the result still came back ok:true with low displacement.","commonSituations":"Goal coordinates equal the bot's current position; pathfinder stuck against a wall or in a liquid; action result schema changed and no longer reports movedDistance; threshold set too high for short hops; calling expectMoved right after a whitelisted action whose name was recently renamed so it is no longer in nonMovingActions.","solutions":["Check globalThis.lastAction.result.movedDistance via log() before asserting, to see the actual displacement.","Lower the threshold or omit it to use the 0.5 default if the move was intentionally short.","Confirm the preceding action is actually a movement action and not misclassified.","If a movement action was renamed, add the new name to the nonMovingActions list in the planner bootstrap, or ensure movement actions report movedDistance."],"exampleFix":"// before\n//   await use('moveTo', { x: 10, y: 64, z: -5 })\n//   expectMoved(2)  // throws if bot only nudged 0.3 blocks\n//\n// after\n//   const r = await use('moveTo', { x: 10, y: 64, z: -5 })\n//   log('moved', r.result.movedDistance)\n//   expectMoved(0.5, `reached target, moved ${r.result?.movedDistance}`)","handlingStrategy":"validation","validationCode":"// Before expectMoved, confirm the last action reports telemetry:\n// const r = globalThis.lastAction?.result\n// if (typeof r?.movedDistance === 'number') {\n//   expectMoved(threshold, `displaced ${r.movedDistance}`)\n// } else {\n//   log('expectMoved skipped: no movedDistance on last action')\n// }","typeGuard":"function hasMovedDistance(r: unknown): r is { movedDistance: number } {\n  return !!r && typeof r === 'object' && typeof (r as any).movedDistance === 'number'\n}","tryCatchPattern":null,"preventionTips":["Only call expectMoved after a movement action (not a whitelisted non-moving action).","Log lastAction.result.movedDistance before asserting to see the real displacement.","Use a threshold consistent with the movement action's stopping radius.","If a movement action was renamed, add it to or keep it out of nonMovingActions accordingly."],"tags":["llm-planner","sandbox","assertion","movement","expectmoved"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}