GoogleContainerTools/skaffold · error

artifact %s cannot use inferred file sync when the ko.main f

Error message

artifact %s cannot use inferred file sync when the ko.main field contains the '...' wildcard. Instead, specify the path to the main package without using wildcards

What it means

When a ko artifact uses inferred file sync (sync.infer), the ko.main field must be a concrete package path. If ko.main contains the Go wildcard '...' (e.g. ./...), Skaffold cannot resolve a single kodata root for inferred sync, so it rejects the combination and asks you to point at the main package directly.

Source

Thrown at pkg/skaffold/schema/validation/validation.go:626

		}
		cfgErrs = append(cfgErrs, ErrorWithLocation{
			Error:    fmt.Errorf("artifact %s has invalid Jib plugin type '%s'", a.ImageName, t),
			Location: cfg.YAMLInfos.LocateField(cfg.Build.Artifacts[i].JibArtifact, "Type"),
		})
	}
	return
}

// validateKoSync ensures that infer sync patterns contain the `kodata` string, since infer sync for the ko builder only supports static assets.
func validateKoSync(cfg *parser.SkaffoldConfigEntry, artifacts []*latest.Artifact) []ErrorWithLocation {
	var cfgErrs []ErrorWithLocation
	for i, a := range artifacts {
		if a.KoArtifact == nil || a.Sync == nil {
			continue
		}
		if len(a.Sync.Infer) > 0 && strings.Contains(a.KoArtifact.Main, "...") {
			cfgErrs = append(cfgErrs, ErrorWithLocation{
				Error:    fmt.Errorf("artifact %s cannot use inferred file sync when the ko.main field contains the '...' wildcard. Instead, specify the path to the main package without using wildcards", a.ImageName),
				Location: cfg.YAMLInfos.LocateField(cfg.Build.Artifacts[i].KoArtifact, "Main"),
			})
		}
		for _, pattern := range a.Sync.Infer {
			if !strings.Contains(pattern, "kodata") {
				cfgErrs = append(cfgErrs, ErrorWithLocation{
					Error:    fmt.Errorf("artifact %s has an invalid pattern %s for inferred file sync with the ko builder. The pattern must specify the 'kodata' directory. For instance, if you want to sync all static content, and your main package is in the workspace directory, you can use the pattern 'kodata/**/*'", a.ImageName, pattern),
					Location: cfg.YAMLInfos.LocateField(cfg.Build.Artifacts[i].Sync, "Infer"),
				})
			}
		}
	}
	return cfgErrs
}

// validateArtifactTypes checks that the artifact types are compatible with the specified builder.
func validateArtifactTypes(cfg *parser.SkaffoldConfigEntry, bc latest.BuildConfig) []ErrorWithLocation {
	cfgErrs := []ErrorWithLocation{}

View on GitHub (pinned to a1189de023)

Solutions

  1. Change ko.main to the explicit path of the main package (e.g. `./cmd/server`) without '...'
  2. Remove the sync.infer section if wildcard main is required
  3. Use explicit sync manual/manual patterns instead of inferred sync

Example fix

# before
build:
  artifacts:
    - image: myapp
      ko:
        main: ./...
      sync:
        infer:
          - '**/*.go'
# after
build:
  artifacts:
    - image: myapp
      ko:
        main: ./cmd/myapp
      sync:
        infer:
          - '**/*.go'
Defensive patterns

Strategy: validation

Validate before calling

if (artifact.ko && artifact.sync?.infer?.length && String(artifact.ko.main || '').includes('...')) {
  throw new Error(`artifact '${artifact.imageName}': sync.infer requires ko.main without '...' wildcard`);
}

Type guard

function koSyncCompatible(a) {
  return !(a?.ko && a?.sync?.infer?.length > 0 && String(a.ko.main ?? '').includes('...'));
}

Try / catch

try {
  await skaffold.dev();
} catch (e) {
  if (/cannot use inferred file sync/.test(e.message)) {
    console.error('Point ko.main at the concrete main package path (no ...) or drop sync.infer');
  } else throw e;
}

Prevention

When it happens

Trigger: An artifact with ko: (ko.main containing '...'), a non-empty sync.infer list, processed via ProcessToErrorWithLocation -> validateKoSync.

Common situations: Users copy `main: ./...` from go build habits or module layout docs and then add sync.infer for hot-reload; the combination is unsupported.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/be5d30e2a36ef7a9. Report an issue: GitHub.