{"record":{"id":"5671a119bc7f2f94","repo":"xai-org/x-algorithm","slug":"cannot-convert-nodes-to-pairs-offset-d-nodes","errorCode":null,"errorMessage":"Cannot convert nodes to pairs: offset = %d, nodes to convert = %d (%s)","messagePattern":"Cannot convert nodes to pairs: offset = (.+?), nodes to convert = (.+?) \\((.+?)\\)","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/function/conversion/ToPair.java","lineNumber":79,"sourceCode":"\n  public static ToPair of(\n      String exprText, ASTNode... children) throws SemanticCheckFailure {\n    return new ToPair(exprText, ImmutableList.copyOf(children));\n  }\n\n  @Override\n  @SuppressWarnings(\"unchecked\")  \n  protected Object apply(Context<Runtime> context, Object arg1, Object arg2) {\n    return new Pair(arg1, arg2);\n  }\n\n  public static ImmutableList<ASTNode> convertNodesToPairs(\n      ImmutableList<ASTNode> nodes, int startOffset) throws SemanticCheckFailure {\n    ImmutableList.Builder<ASTNode> builder = ImmutableList.builder();\n    int n = nodes.size();\n    if (n < startOffset\n        || (n - startOffset) % 2 != 0) {\n      throw new SemanticCheckFailure(String.format(\n          \"Cannot convert nodes to pairs: \"\n              + \"offset = %d, nodes to convert = %d (%s)\",\n          startOffset - 1,\n          n - startOffset,\n          n < startOffset ? \"negative\" : \"not even\"));\n    }\n    for (int i = 0; i < startOffset; ++i) {\n      builder.add(nodes.get(i));\n    }\n    for (int i = startOffset; i < n; i += 2) {\n      builder.add(new ToPair(\n          \"ToPair\", ImmutableList.of(nodes.get(i), nodes.get(i + 1))));\n    }\n    return builder.build();\n  }\n}\n","sourceCodeStart":61,"sourceCodeEnd":96,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/function/conversion/ToPair.java#L61-L96","documentation":"Pair-conversion helpers require the remaining nodes (after startOffset) to form complete name/value pairs: the count must be >= startOffset and (n - startOffset) must be even. Odd leftovers or too-few nodes throw SemanticCheckFailure with the offset, node count, and reason ('negative' or 'not even').","triggerScenarios":"Calling a function like Fn(name1, value1, name2) — an odd number of pair arguments; or passing fewer nodes than the fixed prefix (e.g. zero pair args where at least one pair is required by offset).","commonSituations":"Missing the value half of a name: value argument, trailing commas in generated rule text, or off-by-one when building children lists programmatically.","solutions":["Ensure arguments after the fixed prefix come in name/value pairs — add the missing half","Check for trailing/dangling arguments in the call","When generating code, assert even (args.length - prefix) before emitting"],"exampleFix":"// before\nFn(prefix, name1, value1, orphanName)\n// after\nFn(prefix, name1, value1, orphanName, orphanValue)","handlingStrategy":"validation","validationCode":"// host code before convertNodesToPairs\nint rem = nodes.size() - startOffset;\nif (nodes.size() < startOffset || rem % 2 != 0) {\n  throw new IllegalArgumentException(\"pair arguments must be even after offset\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always supply complete name/value argument pairs","Watch for trailing arguments in generated rule text","Assert even arg counts in code generators"],"tags":["botmaker","semantic-check","pair-argument","arity"],"backgroundTag":"unbalanced-pair-arguments","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}