pinpoint-apm/pinpoint · error · IllegalArgumentException

invalid transactionId

Error message

invalid transactionId:${transactionId}

What it means

After locating the agentId segment, parseTransactionId validates it with IdValidateUtils.checkId. If the agentId substring contains characters or a length outside the allowed identifier rules, an IllegalArgumentException 'invalid transactionId:<id>' is thrown, because a malformed agentId means the string is not a legitimate Pinpoint transactionId.

Solutions

  1. Inspect the agentId segment of the string against IdValidateUtils rules (allowed characters and max length) and fix the source string.
  2. Fix the agent's applicationName/agentId configuration to use only valid identifier characters so future transactionIds parse.
  3. Validate the transactionId with the same check before parsing; trim whitespace and URL-decode inputs coming from links or logs.

Example fix

// before
TransactionId id = TransactionIdUtils.parseTransactionId(rawId.trim());
// after
if (IdValidateUtils.checkId(rawId.trim(), 0, rawId.indexOf(TransactionIdUtils.TRANSACTION_ID_DELIMITER))) {
    TransactionId id = TransactionIdUtils.parseTransactionId(rawId.trim());
}
Defensive patterns

Strategy: validation

Validate before calling

boolean validAgentSegment(String id) {
    int i = id.indexOf(TransactionIdUtils.TRANSACTION_ID_DELIMITER);
    return i > 0 && IdValidateUtils.checkId(id, 0, i);
}
// call parseTransactionId only if validAgentSegment(rawId)

Try / catch

try {
    TransactionId id = TransactionIdUtils.parseTransactionId(rawId);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("invalid transactionId")) {
        logger.warn("transactionId has invalid agentId segment: {}", rawId);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling TransactionIdUtils.parseTransactionId with a string whose first delimiter-delimited segment (the agentId) fails IdValidateUtils.checkId — e.g. contains illegal characters (spaces, '/', unicode), exceeds the max length, or is empty before the first delimiter.

Common situations: Agent applicationName/agentId configured with disallowed characters when the agent was installed, then that id is embedded in transactionIds the parser rejects; transactionId strings reconstructed by hand or truncated in logs/dashboards; copy-pasted ids carrying whitespace or HTML entities.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/aece28f42b5b48a8. Report an issue: GitHub.

Appendix: source

Thrown at commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/util/TransactionIdUtils.java:92

        // write prefix String
        offset = BytesUtils.writeVar32(zigZagAgentIdLength, buffer, offset);
        if (agentIdBytes != null) {
            offset = BytesUtils.writeBytes(buffer, offset, agentIdBytes);
        }
        offset = BytesUtils.writeVar64(agentStartTime, buffer, offset);
        BytesUtils.writeVar64(transactionSequence, buffer, offset);
        return buffer;
    }

    public static TransactionId parseTransactionId(final String transactionId) {
        Objects.requireNonNull(transactionId, "transactionId");

        final int agentIdIndex = nextIndex(transactionId, 0);
        if (agentIdIndex == -1) {
            throw new IllegalArgumentException("agentIndex not found:" + transactionId);
        }
        if (!IdValidateUtils.checkId(transactionId, 0, agentIdIndex)) {
            throw new IllegalArgumentException("invalid transactionId:" + transactionId);
        }
        final String agentId = transactionId.substring(0, agentIdIndex);

        final int agentStartTimeIndex = nextIndex(transactionId, agentIdIndex + 1);
        if (agentStartTimeIndex == -1) {
            throw new IllegalArgumentException("agentStartTimeIndex not found:" + transactionId);
        }
        final long agentStartTime = parseLong(transactionId, agentIdIndex + 1, agentStartTimeIndex);

        int transactionSequenceIndex = nextIndex(transactionId, agentStartTimeIndex + 1);
        if (transactionSequenceIndex == -1) {
            // next index may not exist since default value does not have a delimiter after transactionSequence.
            // may need fixing when id spec changes
            transactionSequenceIndex = transactionId.length();
        }
        final long transactionSequence = parseLong(transactionId, agentStartTimeIndex + 1, transactionSequenceIndex);
        return TransactionId.of(agentId, agentStartTime, transactionSequence);
    }

View on GitHub (pinned to 744c3d3075)