googleapis/mcp-toolbox · error
cannot provide both mainJarFile and mainClass
Error message
cannot provide both mainJarFile and mainClass
What it means
BuildBatch enforces mutual exclusivity of the two entrypoint styles: a Dataproc SparkBatch driver must be set either via MainJarFileUri or MainClass, never both. When both mainJarFile and mainClass are non-empty, this error rejects the conflicting request before any API call is made.
Source
Thrown at internal/tools/serverlessspark/serverlesssparkcreatesparkbatch/serverlesssparkcreatesparkbatch.go:85
parameters.NewStringParameter("mainJarFile", "Optional. The gs:// URI of the jar file that contains the main class. Exactly one of mainJarFile or mainClass must be specified.", parameters.WithStringRequired(false)),
parameters.NewStringParameter("mainClass", "Optional. The name of the driver's main class. Exactly one of mainJarFile or mainClass must be specified.", parameters.WithStringRequired(false)),
parameters.NewArrayParameter("jarFiles", "Optional. A list of gs:// URIs of jar files to add to the CLASSPATHs of the Spark driver and tasks.", parameters.NewStringParameter("jarFile", "A jar file URI."), parameters.WithArrayRequired(false)),
parameters.NewArrayParameter("args", "Optional. A list of arguments passed to the driver.", parameters.NewStringParameter("arg", "An argument."), parameters.WithArrayRequired(false)),
parameters.NewStringParameter("version", "Optional. The Serverless runtime version to execute with.", parameters.WithStringRequired(false)),
}
}
func (b *SparkBatchBuilder) BuildBatch(params parameters.ParamValues) (*dataproc.Batch, error) {
paramMap := params.AsMap()
mainJar, _ := paramMap["mainJarFile"].(string)
mainClass, _ := paramMap["mainClass"].(string)
if mainJar == "" && mainClass == "" {
return nil, fmt.Errorf("must provide either mainJarFile or mainClass")
}
if mainJar != "" && mainClass != "" {
return nil, fmt.Errorf("cannot provide both mainJarFile and mainClass")
}
sparkBatch := &dataproc.SparkBatch{}
if mainJar != "" {
sparkBatch.Driver = &dataproc.SparkBatch_MainJarFileUri{MainJarFileUri: mainJar}
} else {
sparkBatch.Driver = &dataproc.SparkBatch_MainClass{MainClass: mainClass}
}
if jarFileUris, ok := paramMap["jarFiles"].([]any); ok {
for _, uri := range jarFileUris {
sparkBatch.JarFileUris = append(sparkBatch.JarFileUris, fmt.Sprintf("%v", uri))
}
} else if mainClass != "" {
return nil, fmt.Errorf("jarFiles is required when mainClass is provided")
}
if args, ok := paramMap["args"].([]any); ok {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Remove either mainJarFile or mainClass from the parameters, keeping exactly one
- If a default is injected by a template/config, delete the redundant field from the tool call
- Re-issue the invoke with the single remaining entrypoint
Example fix
// before
params := map[string]any{"mainJarFile": "gs://b/app.jar", "mainClass": "com.example.Main"}
// after
params := map[string]any{"mainJarFile": "gs://b/app.jar"} Defensive patterns
Strategy: validation
Validate before calling
jar, _ := params["mainJarFile"].(string)
cls, _ := params["mainClass"].(string)
if jar != "" && cls != "" {
return errors.New("drop one: mainJarFile and mainClass are mutually exclusive")
} Try / catch
res, tbErr := tool.Invoke(ctx, src, paramValues, token)
if tbErr != nil && strings.Contains(tbErr.Error(), "cannot provide both mainJarFile and mainClass") {
// strip mainClass (or mainJarFile) and re-invoke
} Prevention
- Prefer mainJarFile for fat JARs; use mainClass+jarFiles only for classpath-style launches
- Strip template-injected defaults before adding your own entrypoint param
- Unit-test param-building code for mutual exclusivity
When it happens
Trigger: Invoking create-spark-batch with both 'mainJarFile' and 'mainClass' set to non-empty strings in the params map.
Common situations: Agents or templates that always populate defaults for both parameters; users copying examples that include both fields; combining a config-level default mainClass with a request-level mainJarFile.
Related errors
- must provide either mainJarFile or mainClass
- jarFiles is required when mainClass is provided
- tool %q config error: parameter %q (index %d) references '%q
- tool %q config error: parameter %q cannot copy value from it
- invalid jobStateMatcher: %s. Supported values: ALL, ACTIVE,
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/1795590642027685.
Report an issue: GitHub.