ory/kratos · error

could not create request

Error message

could not create request: %w

What it means

For file and base64 schemes ReadSchema falls through to fetching the schema over HTTP via retryablehttp. If the HTTP request itself cannot be constructed (malformed URL parsed by NewRequestWithContext), it returns "could not create request". This precedes any network I/O, so it indicates an invalid URI string rather than a server problem.

Solutions

  1. Validate the schema URL parses (url.Parse) and uses http or https
  2. Quote the URI in YAML/config and check for stray spaces or newline characters
  3. Fix the scheme spelling (http:// or https://)
  4. Verify env substitution yields the full intended URL, not an empty string

Example fix

// before
identity_schemas:
  default: htp://localhost:4455/schemas/default.json
// after
identity_schemas:
  default: http://localhost:4455/schemas/default.json
Defensive patterns

Strategy: validation

Validate before calling

// Go: preflight an http(s) schema URI
func schemaURIFetchable(raw string) error {
	u, err := url.Parse(raw)
	if err != nil {
		return fmt.Errorf("schema URI does not parse: %w", err)
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return fmt.Errorf("unsupported scheme %q; use http(s)", u.Scheme)
	}
	req, err := http.NewRequest(http.MethodGet, u.String(), nil)
	if err != nil {
		return fmt.Errorf("invalid schema request URL: %w", err)
	}
	_ = req
	return nil
}

Type guard

func isParseableURL(raw string) bool {
	_, err := url.Parse(raw)
	return err == nil
}

Try / catch

schema, err := h.ReadSchema(ctx, uri)
if err != nil {
	if strings.Contains(err.Error(), "could not create request") {
		return fmt.Errorf("malformed schema URL %q — check scheme and characters", uri)
	}
	return err
}

Prevention

When it happens

Trigger: Identity schema URI with an unsupported/invalid scheme or malformed URL — e.g. "ftp://host/s.json", "http://[bad-ipv6", spaces or control characters in the URL — that retryablehttp.NewRequestWithContext rejects.

Common situations: Unquoted config value where shell/interpolation characters corrupt the URL; typos in the scheme (htp://); env var templating producing an empty or malformed URI; copied URL containing trailing whitespace or hidden characters.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07). Data as JSON: /api/errors/acb8d60315de1063. Report an issue: GitHub.

Appendix: source

Thrown at schema/handler.go:246

func (h *Handler) ReadSchema(ctx context.Context, uri *url.URL) (data []byte, err error) {
	ctx, span := h.r.Tracer(ctx).Tracer().Start(ctx, "schema.Handler.ReadSchema")
	defer otelx.End(span, &err)

	switch uri.Scheme {
	case "file":
		data, err = os.ReadFile(uri.Host + uri.Path) //nolint:gosec
		if err != nil {
			return nil, errors.WithStack(fmt.Errorf("could not read schema file: %w", err))
		}
	case "base64":
		data, err = base64.StdEncoding.DecodeString(strings.TrimPrefix(uri.String(), "base64://"))
		if err != nil {
			return nil, errors.WithStack(fmt.Errorf("could not decode schema file: %w", err))
		}
	default:
		req, err := retryablehttp.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
		if err != nil {
			return nil, errors.WithStack(fmt.Errorf("could not create request: %w", err))
		}
		resp, err := h.r.HTTPClient(ctx).Do(req)
		if err != nil {
			return nil, errors.WithStack(herodot.ErrUpstreamError().WithReason("could not fetch schema").WithError(err.Error()).WithDetail("uri", uri))
		}
		defer func() { _ = resp.Body.Close() }()
		if resp.StatusCode != http.StatusOK {
			if resp.StatusCode == http.StatusNotFound {
				return nil, herodot.ErrNotFound().WithDetail("url", uri)
			}
			return nil, errors.WithStack(herodot.ErrUpstreamError().WithError("upstream error").WithDetail("status_code", resp.StatusCode).WithDetail("uri", uri))
		}
		data, err = io.ReadAll(io.LimitReader(resp.Body, maxSchemaSize))
		if err != nil {
			return nil, errors.WithStack(herodot.ErrUpstreamError().WithReason("could not read schema response").WithError(err.Error()).WithDetail("uri", uri))
		}
	}
	return data, nil

View on GitHub (pinned to b86338da04)