ory/hydra · error
base64decode: %s
Error message
base64decode: %s
What it means
For base64:// sources, FetchBytes decodes the remainder of the URI with standard (padded) base64. If the string is not valid StdEncoding base64, the decode error is wrapped with 'base64decode: <redacted source>'.
Source
Thrown at oryx/fetcher/fetcher.go:136
func (f *Fetcher) FetchBytes(ctx context.Context, source string) ([]byte, error) {
if !slices.ContainsFunc(f.schemes, func(scheme string) bool {
return strings.HasPrefix(source, scheme+"://")
}) {
return nil, errors.WithStack(fmt.Errorf("%w: in source %q: allowed schemes: %s", ErrUnknownScheme, redactedSource(source), strings.Join(f.schemes, ", ")))
}
switch {
case strings.HasPrefix(source, "http://"), strings.HasPrefix(source, "https://"):
return f.fetchRemote(ctx, source)
case strings.HasPrefix(source, "file://"):
b, err := os.ReadFile(strings.TrimPrefix(source, "file://"))
if err != nil {
return nil, errors.Wrapf(err, "read file: %s", redactedSource(source))
}
return b, nil
case strings.HasPrefix(source, "base64://"):
src, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(source, "base64://"))
if err != nil {
return nil, errors.Wrapf(err, "base64decode: %s", redactedSource(source))
}
return src, nil
default:
return nil, errors.Wrap(ErrUnknownScheme, "unknown scheme in source: "+redactedSource(source))
}
}
func (f *Fetcher) fetchRemote(ctx context.Context, source string) (b []byte, err error) {
if f.cache != nil {
cacheKey := sha256.Sum256([]byte(source))
if v, ok := f.cache.Get(cacheKey[:]); ok {
b = make([]byte, len(v))
copy(b, v)
return b, nil
}
defer func() {
if err == nil && len(b) > 0 {
toCache := make([]byte, len(b))View on GitHub (pinned to 4174065ffb)
Solutions
- Re-encode the payload with standard padded base64: base64.StdEncoding.EncodeToString(data) (use `base64` CLI without -w0/-url flags as appropriate).
- If the value is URL-safe base64, convert it (replace - with + and _ with /) and restore '=' padding before storing it.
- Strip all whitespace/newlines from the base64 payload in the config value.
Example fix
// before
source := "base64://eyJhbGciOiJIUzI1NiJ9_..." // URL-safe chars, no padding
// after
source := "base64://" + base64.StdEncoding.EncodeToString([]byte(`{"alg":"HS256"}`)) Defensive patterns
Strategy: validation
Validate before calling
func validateBase64Source(source string) error {
if !strings.HasPrefix(source, "base64://") {
return nil
}
data := strings.TrimSpace(strings.TrimPrefix(source, "base64://"))
_, err := base64.StdEncoding.DecodeString(data)
return err
} Type guard
func isStandardBase64(s string) bool {
_, err := base64.StdEncoding.DecodeString(s)
return err == nil
} Try / catch
b, err := f.FetchContext(ctx, source)
if err != nil && strings.HasPrefix(err.Error(), "base64decode:") {
log.Printf("invalid base64 payload in config: %v", err)
os.Exit(1)
} Prevention
- Generate config values with base64.StdEncoding.EncodeToString, never hand-trim padding.
- Convert URL-safe base64 (-, _) to standard base64 before embedding in base64:// URIs.
- Strip newlines/whitespace when copying base64 from files or certificates.
When it happens
Trigger: Calling FetchContext/FetchBytes with base64://<data> where <data> contains URL-safe characters (-, _), is missing padding, or contains whitespace/invalid characters — anything base64.StdEncoding.DecodeString rejects.
Common situations: Pasting URL-safe base64 (base64url from JWTs) into a base64:// config value; trimming '=' padding manually; copying base64 with newlines from certificates or editors.
Related errors
- cookiex: cookie could not be decoded
- unable to load TLS certificate for interface %s: %w
- %w: in source %q: allowed schemes: %s
- unable to base64 decode the TLS certificate: %v
- unable to base64 decode the TLS private key: %v
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/1a36e7c011e0fcb9.
Report an issue: GitHub.