apache/beam · error · IllegalArgumentException
Project and location must both be provided if one is…
Error message
Project and location must both be provided if one is provided
What it means
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.
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).
Example fix
// before
GeminiModelHandlerParameters params = GeminiModelHandlerParameters.builder().setProject("my-project").build();
// after
GeminiModelHandlerParameters params = GeminiModelHandlerParameters.builder().setProject("my-project").setLocation("us-central1").build(); Defensive patterns
Strategy: validation
Validate before calling
if (params.getApiKey() == null && ((params.getProject() == null) != (params.getLocation() == null))) { throw new IllegalArgumentException("project and location must be set together for Vertex AI"); } Prevention
- 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
When it happens
Trigger: Constructing GeminiModelHandler with GeminiModelHandlerParameters where getProject() != null but getLocation() == null, or getLocation() != null but getProject() == null, while getApiKey() is null (Vertex AI path).
Common situations: 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.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- A 'datagen' table requires either 'rows-per-second' (for…
- A schema was provided without a data format (or viceversa)…
- Batch size is too large! It should be smaller or equal than
- BigQuery temp location expected a valid 'gs://' path, but…
- boolean cross product parameter required to explode more…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/bdd8932e32c762ec.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/ml/inference/gemini/src/main/java/org/apache/beam/sdk/ml/inference/gemini/GeminiModelHandler.java:60
@Override
public void createClient(GeminiModelParameters<InputT, OutputT> parameters) {
if (parameters == null) {
throw new NullPointerException("GeminiModelParameters must not be null");
}
this.modelParameters = parameters;
// Configure client based on vertex or API key
if (parameters.getApiKey() != null) {
if (parameters.getProject() != null || parameters.getLocation() != null) {
throw new IllegalArgumentException("Project and location must be null if API key is set");
}
this.client = Client.builder().apiKey(parameters.getApiKey()).build();
} else {
Client.Builder builder = Client.builder();
if (parameters.getProject() != null && parameters.getLocation() != null) {
builder.vertexAI(true).project(parameters.getProject()).location(parameters.getLocation());
} else if (parameters.getProject() != null || parameters.getLocation() != null) {
throw new IllegalArgumentException(
"Project and location must both be provided if one is provided");
}
this.client = builder.build();
}
}
@Override
public Iterable<PredictionResult<InputT, OutputT>> request(List<InputT> input) {
try {
GeminiRequestFunction<InputT, OutputT> requestFn = modelParameters.getRequestFn();
List<OutputT> responses = requestFn.apply(modelParameters.getModelName(), input, client);
if (responses.size() != input.size()) {
throw new IllegalStateException("Number of responses must match number of inputs");
}
List<PredictionResult<InputT, OutputT>> results = new ArrayList<>();
for (int i = 0; i < input.size(); i++) {View on GitHub (pinned to 12126d8942)