{"record":{"id":"f7002013afdb6c80","repo":"apache/beam","slug":"project-and-location-must-be-null-if-api-key-is-set","errorCode":null,"errorMessage":"Project and location must be null if API key is set","messagePattern":"Project and location must be null if API key is set","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/ml/inference/gemini/src/main/java/org/apache/beam/sdk/ml/inference/gemini/GeminiModelHandler.java","lineNumber":52,"sourceCode":" */\n@SuppressWarnings(\"nullness\")\npublic class GeminiModelHandler<InputT extends BaseInput, OutputT extends BaseResponse>\n    implements BaseModelHandler<GeminiModelParameters<InputT, OutputT>, InputT, OutputT> {\n\n  private transient Client client;\n  private GeminiModelParameters<InputT, OutputT> modelParameters;\n\n  @Override\n  public void createClient(GeminiModelParameters<InputT, OutputT> parameters) {\n    if (parameters == null) {\n      throw new NullPointerException(\"GeminiModelParameters must not be null\");\n    }\n    this.modelParameters = parameters;\n\n    // Configure client based on vertex or API key\n    if (parameters.getApiKey() != null) {\n      if (parameters.getProject() != null || parameters.getLocation() != null) {\n        throw new IllegalArgumentException(\"Project and location must be null if API key is set\");\n      }\n      this.client = Client.builder().apiKey(parameters.getApiKey()).build();\n    } else {\n      Client.Builder builder = Client.builder();\n      if (parameters.getProject() != null && parameters.getLocation() != null) {\n        builder.vertexAI(true).project(parameters.getProject()).location(parameters.getLocation());\n      } else if (parameters.getProject() != null || parameters.getLocation() != null) {\n        throw new IllegalArgumentException(\n            \"Project and location must both be provided if one is provided\");\n      }\n      this.client = builder.build();\n    }\n  }\n\n  @Override\n  public Iterable<PredictionResult<InputT, OutputT>> request(List<InputT> input) {\n    try {\n      GeminiRequestFunction<InputT, OutputT> requestFn = modelParameters.getRequestFn();","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/ml/inference/gemini/src/main/java/org/apache/beam/sdk/ml/inference/gemini/GeminiModelHandler.java#L34-L70","documentation":"GeminiModelHandler supports two mutually exclusive auth modes: an API key (Gemini API) or Vertex AI (project + location). createClient enforces that when an API key is set, project and location must be null; otherwise this IllegalArgumentException is thrown because the two credential modes conflict.","triggerScenarios":"Building GeminiModelParameters with both setApiKey(...) and setProject(...)/setLocation(...), then calling createClient, which detects the conflicting combination.","commonSituations":"Copy-pasting Vertex AI config (project/location) into an API-key setup or vice versa; environment-driven config that sets all variables regardless of auth mode.","solutions":["Remove setProject/setLocation if you authenticate with an API key.","Remove setApiKey and supply both project and location if you intend to use Vertex AI.","Make your config loading conditional: only populate vertex fields when apiKey is absent (and vice versa)."],"exampleFix":"// before\nparams.setApiKey(key); params.setProject(\"my-proj\"); params.setLocation(\"us-central1\");\n// after (API key mode)\nparams.setApiKey(key);","handlingStrategy":"validation","validationCode":"if (params.getApiKey() != null && (params.getProject() != null || params.getLocation() != null)) {\n  throw new IllegalArgumentException(\"API key mode conflicts with Vertex AI project/location\");\n}","typeGuard":"boolean isConsistentAuth(GeminiModelParameters<?,?> p) { return p.getApiKey() == null ? (p.getProject() != null && p.getLocation() != null) : (p.getProject() == null && p.getLocation() == null); }","tryCatchPattern":"try { handler.createClient(params); } catch (IllegalArgumentException e) { throw new IllegalStateException(\"Gemini auth config conflict: \" + e.getMessage(), e); }","preventionTips":["Load auth config exclusively: if apiKey is present, skip vertex fields entirely.","Document to operators which env vars correspond to which auth mode.","Validate parameter combinations in unit tests before pipeline submission."],"tags":["java","apache-beam","gemini","config-conflict"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}