github/copilot-sdk · error · IllegalArgumentException

Unexpected end of JSON

Error message

Unexpected end of JSON

What it means

CopilotToolProcessor's peek() helper reads the current JSON character but throws IllegalArgumentException if the parser position is past the end of the input. This means the JSON ended abruptly while the parser still expected more content — the input is truncated or empty rather than merely malformed.

Solutions

  1. Ensure the full JSON string is received/parsed only after the stream completes.
  2. Check for empty or blank input and short-circuit before invoking the parser.
  3. Catch IllegalArgumentException and treat it as a truncation signal — request regeneration or completion of the tool call.

Example fix

// before
parse(argsChunk); // partial stream
// after
if (argsChunk == null || argsChunk.isBlank()) throw new SkipException();
String complete = bufferUntilStreamClosed(argsChunk);
parse(complete);
Defensive patterns

Strategy: validation

Validate before calling

if (args == null || args.isBlank()) {
    throw new IllegalStateException("Tool arguments are empty — nothing to parse");
}

Type guard

static boolean hasParseableInput(String s) { return s != null && !s.isBlank(); }

Try / catch

try {
    processor.parse(args);
} catch (IllegalArgumentException e) {
    if ("Unexpected end of JSON".equals(e.getMessage())) {
        return Result.incomplete(); // wait for stream completion / regenerate
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing an empty string or a JSON prefix (e.g. {"name": "a", ) to the tool-argument parser; peek() is called when a token or structural character is required but input is exhausted.

Common situations: Streaming LLM responses parsed before completion, arguments truncated by a size limit, empty tool-call argument strings from the model.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/220b129d307ea599. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1170

        }

        private boolean isDigitOneToNine(char c) {
            return c >= '1' && c <= '9';
        }

        private void skipWhitespace() {
            while (pos < input.length() && isJsonWhitespace(input.charAt(pos))) {
                pos++;
            }
        }

        private boolean isJsonWhitespace(char c) {
            return c == ' ' || c == '\t' || c == '\r' || c == '\n';
        }

        private char peek() {
            if (pos >= input.length()) {
                throw new IllegalArgumentException("Unexpected end of JSON");
            }
            return input.charAt(pos);
        }

        private void expect(char c) {
            if (pos >= input.length() || input.charAt(pos) != c) {
                throw new IllegalArgumentException("Expected '" + c + "' at position " + pos + " but got '"
                        + (pos < input.length() ? input.charAt(pos) : "EOF") + "'");
            }
            pos++;
        }

        private boolean tryConsume(char c) {
            if (pos < input.length() && input.charAt(pos) == c) {
                pos++;
                return true;
            }
            return false;

View on GitHub (pinned to cd8cf15dc3)