grpc/grpc-java · error · IllegalArgumentException

Illegal log config pattern:

Error message

Illegal log config pattern: 

What it means

FactoryImpl's per-configuration parser throws IllegalArgumentException('Illegal log config pattern: ' + configuration) when a configuration entry contains an opening '{' whose closing '}' is not the last character of the entry, i.e. trailing characters exist after the option braces.

Solutions

  1. Make the '}' the last character of the entry: 'Service/Method{h:2;m:100}'
  2. Separate multiple entries with ',' instead of appending directly
  3. Remove stray trailing characters after the closing brace

Example fix

// before
"my.Service/MyMethod{h:2}x"
// after
"my.Service/MyMethod{h:2}"
Defensive patterns

Strategy: validation

Validate before calling

for (String entry : config.split(",")) {
  int open = entry.indexOf('{');
  if (open != -1 && entry.indexOf('}') != entry.length() - 1) {
    throw new IllegalStateException("Trailing chars after '}': " + entry);
  }
}

Try / catch

try {
  BinlogHelper h = new BinlogHelper.FactoryImpl(sink, configStr);
} catch (IllegalArgumentException e) {
  // message echoes the offending configuration; fix and retry once
}

Prevention

When it happens

Trigger: Passing a binary-log config entry like 'svc/Method{h}extra' (characters after '}') to FactoryImpl used by GRPC_BINARY_LOG_CONFIG parsing.

Common situations: Typos in the binary log env var, concatenating entries without a proper separator, or copy-paste errors leaving stray characters after braces.

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


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/35e9b7c597784c88. Report an issue: GitHub.

Appendix: source

Thrown at services/src/main/java/io/grpc/protobuf/services/BinlogHelper.java:629

      checkNotNull(sink, "sink");
      BinlogHelper globalLog = null;
      Map<String, BinlogHelper> perServiceLogs = new HashMap<>();
      Map<String, BinlogHelper> perMethodLogs = new HashMap<>();
      Set<String> blacklistedMethods = new HashSet<>();
      if (configurationString != null && configurationString.length() > 0) {
        for (String configuration : Splitter.on(',').split(configurationString)) {
          int leftCurly = configuration.indexOf('{');
          // '*' for global, 'service/*' for service glob, or 'service/method' for fully qualified
          String methodOrSvc;
          // An expression originally wrapped in curly braces; like {m:256,h:256}, {m:256}, {h:256}
          String binlogOptionStr;
          if (leftCurly == -1) {
            methodOrSvc = configuration;
            binlogOptionStr = null;
          } else {
            int rightCurly = configuration.indexOf('}', leftCurly);
            if (rightCurly != configuration.length() - 1) {
              throw new IllegalArgumentException("Illegal log config pattern: " + configuration);
            }
            methodOrSvc = configuration.substring(0, leftCurly);
            // option without the curly braces
            binlogOptionStr = configuration.substring(leftCurly + 1, configuration.length() - 1);
          }
          if (methodOrSvc.isEmpty()) {
            throw new IllegalArgumentException("Illegal log config pattern: " + configuration);
          }
          if (methodOrSvc.equals("*")) {
            // parse config for "*"
            checkState(
                globalLog == null,
                "Duplicate entry, this is fatal: " + configuration);
            globalLog = createBinaryLog(sink, binlogOptionStr);
            logger.log(Level.INFO, "Global binlog: {0}", binlogOptionStr);
          } else if (isServiceGlob(methodOrSvc)) {
            // parse config for a service, e.g. "service/*"
            String service = MethodDescriptor.extractFullServiceName(methodOrSvc);

View on GitHub (pinned to 64daddc1f3)