uber-go/zap · error

query parameters not allowed with file URLs: got %v

Error message

query parameters not allowed with file URLs: got %v

What it means

newFileSinkFromURL rejects file:// URLs with query parameters (the part after '?'). Queries cannot apply to local files, so zap fails fast rather than ignoring them.

Source

Thrown at sink.go:138

// particular scheme.
//
// All schemes must be ASCII, valid under section 0.1 of RFC 3986
// (https://tools.ietf.org/html/rfc3983#section-3.1), and must not already
// have a factory registered. Zap automatically registers a factory for the
// "file" scheme.
func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error {
	return _sinkRegistry.RegisterSink(scheme, factory)
}

func (sr *sinkRegistry) newFileSinkFromURL(u *url.URL) (Sink, error) {
	if u.User != nil {
		return nil, fmt.Errorf("user and password not allowed with file URLs: got %v", u)
	}
	if u.Fragment != "" {
		return nil, fmt.Errorf("fragments not allowed with file URLs: got %v", u)
	}
	if u.RawQuery != "" {
		return nil, fmt.Errorf("query parameters not allowed with file URLs: got %v", u)
	}
	// Error messages are better if we check hostname and port separately.
	if u.Port() != "" {
		return nil, fmt.Errorf("ports not allowed with file URLs: got %v", u)
	}
	if hn := u.Hostname(); hn != "" && hn != "localhost" {
		return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u)
	}

	return sr.newFileSinkFromPath(u.Path)
}

func (sr *sinkRegistry) newFileSinkFromPath(path string) (Sink, error) {
	switch path {
	case "stdout":
		return nopCloserSink{os.Stdout}, nil
	case "stderr":
		return nopCloserSink{os.Stderr}, nil

View on GitHub (pinned to bbd4ecbd87)

Solutions

  1. Remove the query string from the file URL.
  2. Configure rotation via lumberjack or zap's own rotation hooks instead of URL parameters.
  3. Use a plain absolute path for file outputs.

Example fix

// before
zap.Open("file:///var/log/app.log?maxsize=100")
// after
zap.Open("file:///var/log/app.log") // use lumberjack for rotation
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(dest)
if err == nil && u.Scheme == "file" && u.RawQuery != "" {
    return fmt.Errorf("file URL must not contain query parameters: %s", dest)
}

Try / catch

if _, err := zap.Open(dest); err != nil {
    if strings.Contains(err.Error(), "query parameters not allowed") {
        return fmt.Errorf("remove '?...' from file URL %q", dest)
    }
    return err
}

Prevention

When it happens

Trigger: Passing file:///var/log/app.log?rotate=daily to zap.Open expecting rotation options; reusing a URL from an HTTP-based sink (which accepts query params) with a file scheme.

Common situations: Developers expecting file query options (buffering, rotation) to work like database DSNs; shared config generators appending cache-busting or option parameters.

Related errors


AI-assisted analysis of uber-go/zap@bbd4ecbd87 (2026-08-31). Data as JSON: /api/errors/62eb7965ef8881b8. Report an issue: GitHub.