googleapis/mcp-toolbox · error

jarFiles is required when mainClass is provided

Error message

jarFiles is required when mainClass is provided

What it means

A Spark batch that runs via mainClass needs the class on the driver classpath, which comes from jarFileUris. BuildBatch enforces that when mainClass is provided and no 'jarFiles' array parameter is present, the request is invalid — the jar containing the class must be supplied. Note the check triggers when jarFiles is absent entirely (type assertion to []any fails), not when it is merely empty.

Source

Thrown at internal/tools/serverlessspark/serverlesssparkcreatesparkbatch/serverlesssparkcreatesparkbatch.go:100

		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 {
		for _, arg := range args {
			sparkBatch.Args = append(sparkBatch.Args, fmt.Sprintf("%v", arg))
		}
	}

	return &dataproc.Batch{
		BatchConfig: &dataproc.Batch_SparkBatch{
			SparkBatch: sparkBatch,
		},
	}, nil
}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Add a 'jarFiles' array parameter containing the URIs of JARs that provide the main class
  2. If jarFiles was passed as a string, convert it to a JSON array (e.g. ["gs://bucket/app.jar"])
  3. Alternatively, use mainJarFile instead of mainClass+jarFiles to point directly at the application JAR

Example fix

// before
params := map[string]any{"mainClass": "com.example.Main", "jarFiles": "gs://b/app.jar"}
// after
params := map[string]any{"mainClass": "com.example.Main", "jarFiles": []any{"gs://b/app.jar"}}
Defensive patterns

Strategy: validation

Validate before calling

cls, _ := params["mainClass"].(string)
jars, ok := params["jarFiles"].([]any)
if cls != "" && (!ok || len(jars) == 0) {
    return errors.New("jarFiles array required when mainClass is set")
}

Type guard

func hasJarFiles(params map[string]any) bool {
    _, ok := params["jarFiles"].([]any)
    return ok
}

Try / catch

res, tbErr := tool.Invoke(ctx, src, paramValues, token)
if tbErr != nil && strings.Contains(tbErr.Error(), "jarFiles is required when mainClass is provided") {
    // add jarFiles: ["gs://..."] and re-invoke
}

Prevention

When it happens

Trigger: Invoking create-spark-batch with mainClass set but with no 'jarFiles' parameter at all (key missing or not a []any array, e.g. a single string instead of a list).

Common situations: Users assuming the main class is already bundled in the cluster image; passing jarFiles as a comma-separated string rather than an array so the []any assertion fails; agents generating mainClass-only calls.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/29287a0476ac83bb. Report an issue: GitHub.