{"record":{"id":"bdd8932e32c762ec","repo":"apache/beam","slug":"project-and-location-must-both-be-provided-if-one-is","errorCode":null,"errorMessage":"Project and location must both be provided if one is provided","messagePattern":"Project and location must both be provided if one is provided","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":60,"sourceCode":"  @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();\n      List<OutputT> responses = requestFn.apply(modelParameters.getModelName(), input, client);\n\n      if (responses.size() != input.size()) {\n        throw new IllegalStateException(\"Number of responses must match number of inputs\");\n      }\n\n      List<PredictionResult<InputT, OutputT>> results = new ArrayList<>();\n      for (int i = 0; i < input.size(); i++) {","sourceCodeStart":42,"sourceCodeEnd":78,"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#L42-L78","documentation":"The GeminiModelHandler constructor validates that Vertex AI configuration is consistent. When running against Vertex AI (no API key), both a project and a location must be supplied; supplying only one is ambiguous, so the handler rejects it with this IllegalArgumentException before any client is built.","triggerScenarios":"Constructing GeminiModelHandler with GeminiModelHandlerParameters where getProject() != null but getLocation() == null, or getLocation() != null but getProject() == null, while getApiKey() is null (Vertex AI path).","commonSituations":"Developers set the GCP project but forget the region (e.g. us-central1), or configure the location via env var while the project comes from pipeline options and one of them is empty. Often seen when copying examples that use the API-key path and partially switching to Vertex AI.","solutions":["Set both project and location in the GeminiModelHandlerParameters (e.g. project=\"my-gcp-project\", location=\"us-central1\").","If you intend to use the Gemini Developer API instead, set apiKey and remove the partial project/location config.","Verify pipeline options/env vars actually populate both fields (log them before constructing the handler)."],"exampleFix":"// before\nGeminiModelHandlerParameters params = GeminiModelHandlerParameters.builder().setProject(\"my-project\").build();\n// after\nGeminiModelHandlerParameters params = GeminiModelHandlerParameters.builder().setProject(\"my-project\").setLocation(\"us-central1\").build();","handlingStrategy":"validation","validationCode":"if (params.getApiKey() == null && ((params.getProject() == null) != (params.getLocation() == null))) { throw new IllegalArgumentException(\"project and location must be set together for Vertex AI\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set project and location as a pair in Vertex AI mode","Validate GeminiModelHandlerParameters in pipeline option parsing before building the handler","Log resolved config values once at pipeline construction"],"tags":["java","configuration","vertex-ai"],"backgroundTag":"conflicting-config-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"}