googleapis/mcp-toolbox · error

must provide either mainJarFile or mainClass

Error message

must provide either mainJarFile or mainClass

What it means

BuildBatch assembles a Dataproc SparkBatch from tool parameters and requires exactly one of mainJarFile or mainClass to identify the application entrypoint. If neither parameter is supplied (both resolve to empty strings), the batch cannot be constructed and this validation error is returned to the caller.

Source

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

func (b *SparkBatchBuilder) Parameters() parameters.Parameters {
	return parameters.Parameters{
		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")

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Include either mainJarFile (URI to the driver JAR) or mainClass (fully-qualified class name) in the tool call parameters
  2. If a non-entrypoint param set is intended, verify parameter names are spelled exactly 'mainJarFile'/'mainClass'
  3. Ensure the values are plain JSON strings, not null or nested objects

Example fix

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

Strategy: validation

Validate before calling

jar, _ := params["mainJarFile"].(string)
cls, _ := params["mainClass"].(string)
if jar == "" && cls == "" {
    return errors.New("supply exactly one of mainJarFile or mainClass")
}

Try / catch

res, tbErr := tool.Invoke(ctx, src, paramValues, token)
if tbErr != nil && strings.Contains(tbErr.Error(), "must provide either mainJarFile or mainClass") {
    // prompt caller/LLM to add an entrypoint parameter and retry once
}

Prevention

When it happens

Trigger: Invoking the serverless-spark-create-spark-batch tool with a params map lacking both 'mainJarFile' and 'mainClass' keys, or supplying them as empty strings / non-string values that fail the type assertion to string.

Common situations: LLM/agent omitting optional-looking parameters in generated tool calls; clients sending only jarFiles/args without an entrypoint; params passed as non-string types (e.g. numbers) silently becoming empty strings.

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/5fda7764ae3153dc. Report an issue: GitHub.