pinpoint-apm/pinpoint · error · OracleConnectionStringException

syntax error. Expected token='(' :<token>

Error message

syntax error. Expected token='(' :<token>

What it means

checkStartToken() verifies that the first token of the descriptor is '(' (the singleton TOKEN_KEY_START_OBJECT). When some other token arrives first it throws 'syntax error. Expected token='(' :<token>', including the actual token text. The URL after the '@' prefix must begin a parenthesized key-value tree.

Source

Thrown at agent-module/plugins/oracle-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/oracle/parser/OracleNetConnectionDescriptorTokenizer.java:187

    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());
        }
    }

    public void checkEndToken() {
        Token token = this.nextToken();
        if (token == null) {
            throw new OracleConnectionStringException("parse error. token is null. Expected token=')");

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Start the URL after '@' with '(' — use the full (DESCRIPTION=...) form for descriptor parsing
  2. If you have a TNS alias or host:port:SID, don't route it through the descriptor parser; use the matching URL form instead
  3. Strip any characters between '@' and the first '('
  4. Validate the URL shape before parsing: everything after '@' should start with '(' when a descriptor is intended

Example fix

// before
String url = "jdbc:oracle:thin:@ORCL"; // TNS alias, not a descriptor
// after
String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=db)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))";
Defensive patterns

Strategy: validation

Validate before calling

boolean descriptorStartsWithParen(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 descriptor must start with '(' after '@': {}", url, e);
    throw new ConfigurationException("Expected '(' at descriptor start", e);
}

Prevention

When it happens

Trigger: A driver URL whose post-'@' section starts with a literal or other token instead of '(' — e.g. jdbc:oracle:thin:@host:1521:SID routed through the descriptor parser, or '( DESCRIPTION' style stray characters before the paren.

Common situations: Using the easy-connect (host:port/service) form while the descriptor parser is invoked; extra text or whitespace tokens before '('; mixing TNS alias names ('@ORCL') into a parser expecting a full descriptor.

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.

Related errors


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