{"record":{"id":"42dc87ec2a401024","repo":"apache/iceberg","slug":"cannot-specify-both-s-and-s","errorCode":null,"errorMessage":"Cannot specify both %s and %s","messagePattern":"Cannot specify both (.+?) and (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"gcp/src/main/java/org/apache/iceberg/gcp/auth/GoogleAuthManager.java","lineNumber":89,"sourceCode":"  public GoogleAuthManager(String managerName) {\n    this.name = managerName;\n  }\n\n  public String name() {\n    return name;\n  }\n\n  private void initialize(Map<String, String> properties) {\n    if (initialized) {\n      return;\n    }\n\n    String credentialsPath = properties.get(GCP_CREDENTIALS_PATH_PROPERTY);\n    String credentialsJson = properties.get(GCP_CREDENTIALS_JSON_PROPERTY);\n    boolean useCredentialsPath = credentialsPath != null && !credentialsPath.isEmpty();\n    boolean useCredentialsJson = credentialsJson != null && !credentialsJson.isEmpty();\n    if (useCredentialsPath && useCredentialsJson) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Cannot specify both %s and %s\",\n              GCP_CREDENTIALS_PATH_PROPERTY, GCP_CREDENTIALS_JSON_PROPERTY));\n    }\n\n    String scopesString = properties.getOrDefault(GCP_SCOPES_PROPERTY, DEFAULT_SCOPES);\n    List<String> scopes =\n        Strings.isNullOrEmpty(scopesString)\n            ? ImmutableList.of()\n            : ImmutableList.copyOf(SPLITTER.splitToList(scopesString));\n\n    try {\n      if (useCredentialsPath) {\n        LOG.info(\"Using Google credentials from path: {}\", credentialsPath);\n        try (FileInputStream credentialsStream = new FileInputStream(credentialsPath)) {\n          this.credentials = GoogleCredentials.fromStream(credentialsStream).createScoped(scopes);\n        }\n      } else if (useCredentialsJson) {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/gcp/src/main/java/org/apache/iceberg/gcp/auth/GoogleAuthManager.java#L71-L107","documentation":"GoogleAuthManager.initialize rejects configurations that set both the GCP credentials path property and the GCP credentials JSON property, since the credential source is ambiguous. It throws IllegalArgumentException('Cannot specify both %s and %s').","triggerScenarios":"Catalog/session properties contain both gcp credentials-path and gcp credentials-json (or their configured property names) with non-empty values.","commonSituations":"Merging config from multiple sources (catalog properties + Hadoop conf + environment) where one source sets a path and another sets inline JSON, or copy-pasting a full example config.","solutions":["Remove one of the two properties — keep either the credentials file path or the inline JSON","Audit all config layers (catalog properties, Hadoop conf, env) for duplicate GCP auth settings","Standardize on inline JSON for portability or path for secret-file deployments"],"exampleFix":"// before\nprops.put(\"gcp.credentials-path\", \"/path/sa.json\");\nprops.put(\"gcp.credentials-json\", \"{...}\");\n// after\nprops.put(\"gcp.credentials-json\", \"{...}\"); // single source only","handlingStrategy":"validation","validationCode":"String p = props.get(\"gcp.credentials-path\"); String j = props.get(\"gcp.credentials-json\");\nif (p != null && !p.isEmpty() && j != null && !j.isEmpty()) { throw new IllegalArgumentException(\"Set only one of credentials-path / credentials-json\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep exactly one credential source in config","Audit merged config layers for duplicate GCP auth keys","Document the precedence rule in your deployment config"],"tags":["gcp","config","authentication","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}