golang/go · error

cannot embed %s %s: in invalid directory %s

Error message

cannot embed %s %s: in invalid directory %s

What it means

Companion to 884, same isBadEmbedName check at line 2218, but here dir != file — i.e. an ANCESTOR directory (not the leaf file) has a base name that is invalid for embedding. The offending directory name is reported.

Source

Thrown at src/cmd/go/internal/load/pkg.go:2219

			}

			// Check that directories along path do not begin a new module
			// (do not contain a go.mod).
			for dir := file; len(dir) > len(pkgdir)+1 && !dirOK[dir]; dir = filepath.Dir(dir) {
				if _, err := fsys.Stat(filepath.Join(dir, "go.mod")); err == nil {
					return nil, nil, fmt.Errorf("cannot embed %s %s: in different module", what, rel)
				}
				if dir != file {
					if info, err := fsys.Lstat(dir); err == nil && !info.IsDir() {
						return nil, nil, fmt.Errorf("cannot embed %s %s: in non-directory %s", what, rel, dir[len(pkgdir)+1:])
					}
				}
				dirOK[dir] = true
				if elem := filepath.Base(dir); isBadEmbedName(elem) {
					if dir == file {
						return nil, nil, fmt.Errorf("cannot embed %s %s: invalid name %s", what, rel, elem)
					} else {
						return nil, nil, fmt.Errorf("cannot embed %s %s: in invalid directory %s", what, rel, elem)
					}
				}
			}

			switch {
			default:
				return nil, nil, fmt.Errorf("cannot embed irregular file %s", rel)

			case info.Mode().IsRegular():
				if have[rel] != pid {
					have[rel] = pid
					list = append(list, rel)
				}

			// If the embedfollowsymlinks GODEBUG is set to 1, allow the leaf file to be a
			// symlink (#59924). We don't allow directories to be symlinks and have already
			// checked that none of the parent directories of the file are symlinks in the
			// loop above. The file pointed to by the symlink must be a regular file.

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Rename the offending ancestor directory so every component uses only ASCII letters, digits, dot, underscore, hyphen.
  2. Reorganize the embedded tree to drop the problematic folder level.
  3. If you cannot rename, copy the assets into a cleanly-named directory as a build step.

Example fix

// before: //go:embed assets v2/data.json  (folder has a space)
// after: rename to assets_v2/, then
//go:embed assets_v2/data.json
Defensive patterns

Strategy: validation

Validate before calling

// Same character rule as 884, but applied to every DIRECTORY component
// of the embed path, not just the leaf.
package embedcheck

import (
	"errors"
	"strings"
	"unicode/utf8"
)

func ValidEmbedDirNames(rel string) error {
	for _, seg := range strings.Split(filepath.ToSlash(rel), "/") {
		if seg == "" {
			continue
		}
		for _, r := range seg {
			if r >= utf8.RuneSelf {
				return errors.New("non-ASCII char in embed dir: " + seg)
			}
			switch {
			case 'a' <= r && r <= 'z', 'A' <= r && r <= 'Z', '0' <= r && r <= '9':
			case r == '.', r == '_', r == '-':
			default:
				return errors.New("disallowed char in embed dir: " + seg)
			}
		}
	}
	return nil
}

Prevention

When it happens

Trigger: Embedding `sub dir/file.txt` where the directory `sub dir` contains a space; an embedded tree that contains a folder with parentheses or non-ASCII characters in its name.

Common situations: Folder names created by designers/PMs with spaces or special characters; localized folder names; vendored assets dropped into a folder with a bad name.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/28a80318dc6a69f5. Report an issue: GitHub.