hashicorp/packer · error

%q not implemented

Error message

%q not implemented

What it means

The GitHub plugin-getter only supports HTTP(S) fetch operations. Get() builds an HTTP request based on the URL scheme and, for any scheme other than http/https (the switch's default branch), refuses to proceed. This is a deliberate guard: the getter cannot speak other protocols like file:// or ftp://.

Source

Thrown at packer/plugin-getter/github/getter.go:266

	case "sha256":
		// something like https://github.com/sylviamoss/packer-plugin-comment/releases/download/v0.2.11/packer-plugin-comment_v0.2.11_x5_SHA256SUMS
		u := filepath.ToSlash("https://github.com/" + ghURI.RealRelativePath() + "/releases/download/" + opts.Version() + "/" + opts.PluginRequirement.FilenamePrefix() + opts.Version() + "_SHA256SUMS")
		req, err = g.Client.NewRequest(
			"GET",
			u,
			nil,
		)
		transform = TransformChecksumStream()
	case "zip":
		u := filepath.ToSlash("https://github.com/" + ghURI.RealRelativePath() + "/releases/download/" + opts.Version() + "/" + opts.ExpectedZipFilename())
		req, err = g.Client.NewRequest(
			"GET",
			u,
			nil,
		)

	default:
		return nil, fmt.Errorf("%q not implemented", what)
	}
	if err != nil {
		return nil, err
	}
	log.Printf("[DEBUG] github-getter: getting %q", req.URL)
	resp, err := g.Client.BareDo(ctx, req)
	if err != nil {
		// here BareDo will return an err if the request failed or if the status
		// is not considered a valid http status. So we have to close the body
		// if it's not nil.
		if resp != nil {
			resp.Body.Close()
		}
		switch err := err.(type) {
		case *github.RateLimitError:
			return nil, &plugingetter.RateLimitError{
				SetableEnvVar: ghTokenAccessor,
				Err:           err,

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Use an https:// URL for the plugin download source (e.g. the GitHub release asset URL).
  2. If you need local installs, use `packer plugins install` with the registry path or place binaries in PACKER_PLUGIN_PATH manually instead of routing through this getter.
  3. If a custom scheme is legitimately needed, wrap or fork the getter and add a case in the switch.

Example fix

// before
g.Get(ctx, "file:///opt/plugins/github.com/foo/bar", plugingetter.GET)
// after
g.Get(ctx, "https://github.com/foo/bar/releases/download/...", plugingetter.GET)
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(rawURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
	return fmt.Errorf("github getter requires http(s), got %q", u.Scheme)
}

Type guard

func isHTTPOrHTTPS(u *url.URL) bool { return u != nil && (u.Scheme == "http" || u.Scheme == "https") }

Try / catch

if _, err := g.Get(ctx, u, "GET"); err != nil {
	if strings.Contains(err.Error(), "not implemented") {
		// fall back to the default getter or a local install path
	}
}

Prevention

When it happens

Trigger: Calling Getter.Get(ctx, u, what) where u.Scheme is not "http" or "https" (e.g. a file://, ftp://, or ssh:// URL); the what argument (GET/POST-like verb) is also switched on, so an unrecognized verb string reaches the default case.

Common situations: A plugin URL in required_plugins or PACKER_PLUGIN_PATH points at a non-HTTP source; a misconfigured mirror or proxy URL uses an unsupported scheme; tests or tooling pass a local file path instead of an HTTPS release URL.

Related errors


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