pinpoint-apm/pinpoint · error · OracleConnectionStringException
parse error. token is null
Error message
parse error. token is null
What it means
checkStartToken() consumes the first token of the descriptor and requires it to be the '(' key-start token; if nextToken() returns null (empty or exhausted input) it throws 'parse error. token is null'. The parser was handed nothing to parse after the URL prefix.
Solutions
- Provide the full descriptor after the '@', e.g. jdbc:oracle:thin:@(DESCRIPTION=...)
- Check that the config/env variable holding the descriptor is non-empty and correctly wired
- Fall back to the simple URL format jdbc:oracle:thin:@host:port:SID if a descriptor isn't required
- Add a null/empty check on the JDBC URL in configuration loading and fail with a clear message
Example fix
// before String url = "jdbc:oracle:thin:@" + desc; // desc == "" // after String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=db)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=svc)))";
Defensive patterns
Strategy: validation
Validate before calling
boolean hasDescriptorBody(String url) {
if (url == null) return false;
int at = url.indexOf('@');
return at != -1 && url.substring(at + 1).trim().startsWith("(");
} Try / catch
try {
parser.parse(url);
} catch (OracleConnectionStringException e) {
log.error("Oracle JDBC URL empty after '@': {}", url, e);
throw new ConfigurationException("Missing descriptor after '@'", e);
} Prevention
- Check config wiring so the descriptor variable is actually populated
- Reject empty or prefix-only JDBC URLs at configuration load
- Fall back to jdbc:oracle:thin:@host:port:SID when no descriptor is configured
When it happens
Trigger: Parsing a URL like 'jdbc:oracle:thin:@' with nothing after the '@' — the tokenizer produces no tokens and checkStartToken()'s nextToken() returns null. Also reached via parser flows that call checkStartToken on an empty remainder.
Common situations: Config key containing only the prefix with the descriptor in a separate/missing variable; empty environment variable substituted for the host section; trimmed URL where the descriptor got stripped.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- description_list node not found
- description node not found
- invalid oracle jdbc url. expected token:(thin or oci) url
- parse error. token is null. Expected token='='
- parsing error. expected token:'EOF' token
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/3f63939b7ee222e4.
Report an issue: GitHub.
Appendix: source
Thrown at agent-module/plugins/oracle-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/oracle/parser/OracleNetConnectionDescriptorTokenizer.java:183
}
tokenPosition++;
}
public Token lookAheadToken() {
if (tokenList.size() <= tokenPosition) {
return null;
}
return tokenList.get(tokenPosition);
}
public void setPosition(int position) {
this.position = position;
}
public void checkStartToken() {
Token token = this.nextToken();
if (token == null) {
throw new OracleConnectionStringException("parse error. token is null");
}
// We can check by == because the token object is singleton.
if (!(token == TOKEN_KEY_START_OBJECT)) {
throw new OracleConnectionStringException("syntax error. Expected token='(' :" + token.getToken());
}
}
public void checkEqualToken() {
Token token = this.nextToken();
if (token == null) {
throw new OracleConnectionStringException("parse error. token is null. Expected token='='");
}
// We can check by == because the token object is singleton.
if (!(token == TOKEN_EQUAL_OBJECT)) {
throw new OracleConnectionStringException("Syntax error. Expected token='=' :" + token.getToken());
}
}
View on GitHub (pinned to 744c3d3075)