gohugoio/hugo · error

only esm format is currently supported

Error message

only esm format is currently supported

What it means

Hugo's JS batcher only supports the ES module output format. If externalOptions.Format (compiled from the options map) is set to anything other than "esm" — e.g. "iife", "cjs", "umd" — build() rejects it at batch.go:523-528. An empty format is auto-defaulted to "esm", so the error only fires when a non-esm value is explicitly provided.

Solutions

  1. Set Format to "esm" (the default and only supported value).
  2. Omit Format entirely so it defaults to "esm".
  3. If you need IIFE/UMD output, use Hugo's js.Build resource transform with compatible options instead of the batcher.

Example fix

// before
opts := map[string]any{"format": "iife"}

// after
opts := map[string]any{"format": "esm"}
// or simply omit "format"
Defensive patterns

Strategy: validation

Validate before calling

func validateBatchFormat(opts map[string]any) error {
    if f, ok := opts["format"].(string); ok && f != "" && f != "esm" {
        return fmt.Errorf("only esm format is currently supported (got %q)", f)
    }
    return nil
}

Type guard

func isSupportedFormat(f string) bool { return f == "" || f == "esm" }

Prevention

When it happens

Trigger: Passing options with Format set to "iife", "cjs", or any non-esm string to the JS batch/bundler options (e.g. via js.Build options or the batch config options map).

Common situations: Porting a non-Hugo esbuild config that used IIFE/UMD for legacy browsers; setting target/format options intended for a different bundler; copy-pasting an esbuild snippet with format: 'iife'.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/4ff9a5e738cd9740. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/esbuild/batch.go:527

		}

		state.importerImportContext.Set(s, importContext{
			name:           s,
			resourceGetter: nil,
			dm:             g.dependencyManager,
		})

		addResource(g.id, s, r, true)
	}

	mediaTypes := b.client.d.ResourceSpec.MediaTypes()

	externalOptions := b.configOptions.Compiled().Options
	if externalOptions.Format == "" {
		externalOptions.Format = "esm"
	}
	if externalOptions.Format != "esm" {
		return nil, fmt.Errorf("only esm format is currently supported")
	}

	jsOpts := Options{
		ExternalOptions: externalOptions,
		InternalOptions: InternalOptions{
			DependencyManager: b.dependencyManager,
			Splitting:         true,
			ImportOnResolveFunc: func(imp string, args api.OnResolveArgs) string {
				var importContextPath string
				if args.Kind == api.ResolveEntryPoint {
					importContextPath = args.Path
				} else {
					importContextPath = args.Importer
				}
				importContext, importContextFound := state.importerImportContext.Get(importContextPath)

				// We want to track the dependencies closest to where they're used.
				dm := b.dependencyManager

View on GitHub (pinned to 52c9bd7908)