hashicorp/packer · error

unsupported scope

Error message

unsupported scope: %s

What it means

Inside Generate, g.config.Scope is mapped to a source.Scope; only 'all-layers', '' and 'squashed' are recognized. Any other value returns `unsupported scope: %s`. Normally unreachable because ParseScopeFromArgs and NewGenerator normalize scope, but code that populates Config directly can insert invalid values.

Solutions

  1. Set Scope only via ParseScopeFromArgs, or leave it empty so NewGenerator defaults to squashed
  2. Accept only "squashed" or "all-layers" in the HCL/template config surface and validate early
  3. Update any stored config that holds a non-canonical scope string

Example fix

// before
gen := sbom.NewGenerator(sbom.Config{Scope: scopeFromUser}) // raw, unvalidated
// after
scope, err := sbom.ParseScopeFromArgs(scopeFromUser)
if err != nil { return err }
gen := sbom.NewGenerator(sbom.Config{Scope: scope})
Defensive patterns

Strategy: validation

Validate before calling

scope, err := sbom.ParseScopeFromArgs(cfg.Scope)
if err != nil { return err }
cfg.Scope = scope
gen := sbom.NewGenerator(cfg)

Type guard

func validScope(s string) bool { return s == "" || s == "squashed" || s == "all-layers" }

Try / catch

out, err := gen.Generate(ctx)
if err != nil {
    if strings.HasPrefix(err.Error(), "unsupported scope") { return fmt.Errorf("fix Scope in config: %w", err) }
    return err
}

Prevention

When it happens

Trigger: Constructing sbom.Config{Scope: "directory"} or another raw string and calling Generate without passing it through ParseScopeFromArgs/NewGenerator; config sources bypassing validation (HCL field set to an arbitrary value).

Common situations: Users setting scope via template fields with values like "all-layers:" or "squashed+uncompressed" copied from other tools; programmatic callers of the internal package skipping ParseScopeFromArgs.

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/0d292ec60466f6fd. Report an issue: GitHub.

Appendix: source

Thrown at internal/sbom/generator_syft.go:44

	getSourceCfg := syft.DefaultGetSourceConfig()
	if len(g.config.Exclude) > 0 {
		getSourceCfg = getSourceCfg.WithExcludeConfig(source.ExcludeConfig{Paths: g.config.Exclude})
	}

	src, err := syft.GetSource(ctx, sourceInput, getSourceCfg)
	if err != nil {
		return nil, fmt.Errorf("failed to get source: %w", err)
	}
	defer func() { _ = src.Close() }()

	var scope source.Scope
	switch g.config.Scope {
	case ScopeAllLayers:
		scope = source.AllLayersScope
	case "", ScopeSquashed:
		scope = source.SquashedScope
	default:
		return nil, fmt.Errorf("unsupported scope: %s", g.config.Scope)
	}

	sbomCfg := syft.DefaultCreateSBOMConfig().
		WithSearchConfig(cataloging.SearchConfig{
			Scope: scope,
		}).
		WithParallelism(g.config.Parallelism)

	sbomResult, err := syft.CreateSBOM(ctx, src, sbomCfg)
	if err != nil {
		return nil, fmt.Errorf("failed to create SBOM: %w", err)
	}

	return g.encodeToFormat(sbomResult)
}

// encodeToFormat encodes the SBOM to the requested format.
func (g *Generator) encodeToFormat(sbomData *sbom.SBOM) ([]byte, error) {

View on GitHub (pinned to eb36e3c3e4)