docker/compose · error

invalid OCI artifact

Error message

invalid OCI artifact

What it means

First guard of `validatePathInBase` for `oci://` includes: OCI artifact resources must all live in a single flat directory, so any fragment containing `/` or `\` is rejected outright with the generic 'invalid OCI artifact' message. This differs from the git loader, which allows nested subdirectories.

Source

Thrown at pkg/remote/oci.go:52

	"github.com/docker/cli/cli/command"
	spec "github.com/opencontainers/image-spec/specs-go/v1"

	"github.com/docker/compose/v5/internal/desktop"
	"github.com/docker/compose/v5/internal/oci"
	"github.com/docker/compose/v5/pkg/api"
)

const (
	OCI_REMOTE_ENABLED = "COMPOSE_EXPERIMENTAL_OCI_REMOTE"
	OciPrefix          = "oci://"
)

// validatePathInBase ensures a file path is contained within the base directory,
// as OCI artifact resources must all live within the same folder.
func validatePathInBase(base, unsafePath string) error {
	// Reject paths with path separators regardless of OS
	if strings.ContainsAny(unsafePath, "\\/") {
		return fmt.Errorf("invalid OCI artifact")
	}

	// Join the base with the untrusted path
	targetPath := filepath.Join(base, unsafePath)

	// Get the directory of the target path
	targetDir := filepath.Dir(targetPath)

	// Clean both paths to resolve any .. or . components
	cleanBase := filepath.Clean(base)
	cleanTargetDir := filepath.Clean(targetDir)

	// Check if the target directory is the same as base directory
	if cleanTargetDir != cleanBase {
		return fmt.Errorf("invalid OCI artifact")
	}

	return nil

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Package the OCI artifact so the compose file sits at its root and reference it with no path fragment: `oci://registry/repo:tag`
  2. Use a git:// include instead if you genuinely need nested subdirectory selection

Example fix

# before
include:
  - path: oci://registry.example.com/team/configs:1.0#prod/compose.yaml

# after
include:
  - path: oci://registry.example.com/team/configs:1.0
Defensive patterns

Strategy: validation

Validate before calling

# oci:// fragments must be a bare filename: no / or \
python3 - <<'EOF'
import sys
for arg in sys.argv[1:]:
    if not arg.startswith('oci://'): continue
    frag = arg.split('#',1)[1] if '#' in arg else ''
    if '/' in frag or '\\' in frag:
        sys.exit(f"oci include fragment must be a flat filename: {arg}")
EOF

Prevention

When it happens

Trigger: Including `oci://registry/repo:tag#sub/dir/compose.yaml` — any `#fragment` with a path separator fails, because the extracted files must sit directly in the base directory.

Common situations: Reusing git-include muscle memory (`#subdir/path`) with oci:// includes; OCI artifacts packaged with nested layouts that Compose cannot address.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/55d0712216458085. Report an issue: GitHub.