pinpoint-apm/pinpoint · error · IllegalArgumentException
agentStartTimeIndex not found
Error message
agentStartTimeIndex not found:${transactionId} What it means
TransactionIdUtils.parseTransactionId splits a transactionId string (format: agentId^agentStartTime^transactionSequence) on delimiters. When no second delimiter exists after the agentId, nextIndex returns -1 and this IllegalArgumentException is thrown, meaning the transactionId string is malformed and cannot be decomposed into its components.
Solutions
- Verify the transactionId is produced by TransactionIdUtils.formatString / TransactionId objects, not hand-concatenated
- Check that the string contains the expected delimiters between agentId, agentStartTime, and transactionSequence before calling parseTransactionId
- Validate the id came from a pinpoint span/trace source and was not truncated by storage or logging
- Wrap parseTransactionId in try-catch and treat the input as a malformed/foreign id
Example fix
// before
TransactionId id = TransactionIdUtils.parseTransactionId(agentIdLine);
// after
if (agentIdLine != null && agentIdLine.indexOf(TransactionIdUtils.AGENT_ID_DELIMITER) > -1) {
TransactionId id = TransactionIdUtils.parseTransactionId(agentIdLine);
} else {
throw new IllegalArgumentException("malformed transactionId: " + agentIdLine);
} Defensive patterns
Strategy: validation
Validate before calling
boolean isParseableTransactionId(String s) {
if (s == null) return false;
int first = s.indexOf(TransactionIdUtils.AGENT_ID_DELIMITER);
return first > 0 && s.indexOf(TransactionIdUtils.AGENT_ID_DELIMITER, first + 1) != -1;
} Type guard
boolean isParseableTransactionId(String s) {
if (s == null) return false;
int first = s.indexOf(TransactionIdUtils.AGENT_ID_DELIMITER);
return first > 0 && s.indexOf(TransactionIdUtils.AGENT_ID_DELIMITER, first + 1) != -1;
} Try / catch
try {
TransactionId id = TransactionIdUtils.parseTransactionId(txId);
} catch (IllegalArgumentException e) {
log.warn("malformed transactionId: {}", txId, e);
// treat as foreign/legacy id, skip or fall back
} Prevention
- Only pass transactionIds produced by TransactionIdUtils.formatString or TransactionId objects
- Never hand-concatenate transactionId strings; use the format API with the correct delimiter
- Validate delimiter count before parsing ids from external/log sources
- Handle ids from older pinpoint versions or non-pinpoint sources separately
When it happens
Trigger: Calling TransactionIdUtils.parseTransactionId with a string that has an agentId but no delimiter after it, e.g. 'myAgentId' or 'myAgentId12345' (missing the separator between agentId and agentStartTime).
Common situations: Passing a raw string value (agentId alone, or a traceId copied partially) instead of a full transactionId; hand-building transactionId strings with the wrong delimiter; older/newer pinpoint versions or custom storage rows where the id was truncated or not encoded with TransactionIdUtils.formatString.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- agentIndex not found
- invalid transactionId
- parseLong Error. transactionId
- application serviceType not found. code:, name:
- Cannot add an existing column family :
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/5d223429dffc2dbd.
Report an issue: GitHub.
Appendix: source
Thrown at commons-profiler/src/main/java/com/navercorp/pinpoint/common/profiler/util/TransactionIdUtils.java:98
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);
}
private static int nextIndex(String transactionId, int fromIndex) {
return transactionId.indexOf(TRANSACTION_ID_DELIMITER_CHAR, fromIndex);
}
private static long parseLong(String transactionId, int beginIndex, int endIndex) {View on GitHub (pinned to 744c3d3075)