{"record":{"id":"872133d01dabfb81","repo":"nathanmarz/storm","slug":"anchored-onto-o-after-ack-fail","errorCode":null,"errorMessage":"Anchored onto ${o} after ack/fail","messagePattern":"Anchored onto (.+?) after ack/fail","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"storm-core/src/jvm/backtype/storm/task/ShellBolt.java","lineNumber":226,"sourceCode":"        String msg = (String) action.get(\"msg\");\n        _collector.reportError(new Exception(\"Shell Process Exception: \" + msg));\n    }\n\n    private void handleEmit(Map action) throws InterruptedException {\n        String stream = (String) action.get(\"stream\");\n        if(stream==null) stream = Utils.DEFAULT_STREAM_ID;\n        Long task = (Long) action.get(\"task\");\n        List<Object> tuple = (List) action.get(\"tuple\");\n        List<Tuple> anchors = new ArrayList<Tuple>();\n        Object anchorObj = action.get(\"anchors\");\n        if(anchorObj!=null) {\n            if(anchorObj instanceof String) {\n                anchorObj = Arrays.asList(anchorObj);\n            }\n            for(Object o: (List) anchorObj) {\n                Tuple t = _inputs.get((String) o);\n                if (t == null) {\n                    throw new RuntimeException(\"Anchored onto \" + o + \" after ack/fail\");\n                }\n                anchors.add(t);\n            }\n        }\n        if(task==null) {\n            List<Integer> outtasks = _collector.emit(stream, anchors, tuple);\n            Object need_task_ids = action.get(\"need_task_ids\");\n            if (need_task_ids == null || ((Boolean) need_task_ids).booleanValue()) {\n                _pendingWrites.put(outtasks);\n            }\n        } else {\n            _collector.emitDirect((int)task.longValue(), stream, anchors, tuple);\n        }\n    }\n\n    private void die(Throwable exception) {\n        _exception = exception;\n    }","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/backtype/storm/task/ShellBolt.java#L208-L244","documentation":"When a ShellBolt emits an anchored tuple, each anchor id must still resolve to a pending input tuple in _inputs. If the shell script anchors onto an id that was already acked/failed (removed from the map) or never received, Storm throws this RuntimeException because the anchor tuple cannot be resolved.","triggerScenarios":"Shell process calls emit with an 'anchor' list containing a tuple id that has already been acked/failed, or an id that was never passed to the script, e.g. emitting with anchors=['<old id>'] after acking that tuple.","commonSituations":"Multilang scripts that cache tuple ids and re-emit them later (retry logic), scripts anchoring on ids from previous execute() calls, or scripts that generate anchor ids instead of using the ones received.","solutions":["Only anchor on tuple ids from the CURRENT execute/nextTuple message that have not been acked/failed yet.","Remove any retry/re-emit logic that reuses previously acked tuple ids as anchors.","Emit unanchored (anchors=[] ) if delayed emission is intended, accepting no anchoring guarantees.","Keep anchor emission in the same processing step as the input tuple, before acking it.","Log anchor ids in the script to identify which id is stale."],"exampleFix":"# before\nprocess(tuple)\nack(tuple['id'])\nemit([tuple['id']], [value])  # anchor already acked\n\n# after\nemit([tuple['id']], [value])  # anchor while still pending\nack(tuple['id'])","handlingStrategy":"validation","validationCode":"# before emitting with anchors:\nanchors = [i for i in anchor_ids if i in pending]","typeGuard":"def is_anchorable(anchor_id):\n    return anchor_id in pending","tryCatchPattern":null,"preventionTips":["Anchor only on tuple ids received in the current execute/nextTuple call.","Emit before acking the anchor tuple.","Avoid re-emit/retry logic that reuses old ids; emit unanchored if delayed.","Log anchor ids during development to catch stale references."],"tags":["storm","multilang","shell-bolt","anchoring"],"backgroundTag":"invalid-state-transition","analyzedSha":"cdb116e942666973bc4eaa0df098d5bab82739e7","analyzedAt":"2026-09-12T14:30:00.714Z","contentChangedAt":"2026-09-12T14:30:00.714Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}