router-for-me/CLIProxyAPI · error

invalid_expires_after

invalid_expires_after

Error message

expires_after.anchor must be created_at

What it means

The stream-read callback rejects the call when the receiver Host is nil or its modelStreams bridge is nil. This is a host-side wiring/lifecycle error, not a bad stream ID (a bad ID instead yields 'not open' from the bridge).

Source

Thrown at internal/client/codex/live/client_secret.go:313

		c.JSON(http.StatusOK, response)
		return
	}
	c.JSON(http.StatusOK, clientSecretCreateResponse{
		Value:     token,
		ExpiresAt: expiresAt.Unix(),
		Session:   responseSession,
	})
}

func clientSecretLifetime(expiresAfter *struct {
	Anchor  string `json:"anchor"`
	Seconds int64  `json:"seconds"`
}) (time.Duration, error) {
	if expiresAfter == nil {
		return clientSecretDefaultLifetime, nil
	}
	if expiresAfter.Anchor != "" && expiresAfter.Anchor != "created_at" {
		return 0, errors.New("expires_after.anchor must be created_at")
	}
	minimumSeconds := int64(clientSecretMinimumLifetime / time.Second)
	maximumSeconds := int64(clientSecretMaximumLifetime / time.Second)
	if expiresAfter.Seconds < minimumSeconds || expiresAfter.Seconds > maximumSeconds {
		return 0, fmt.Errorf("expires_after.seconds must be between %d and %d", minimumSeconds, maximumSeconds)
	}
	return time.Duration(expiresAfter.Seconds) * time.Second, nil
}

func normalizeClientSecretSession(session json.RawMessage) (json.RawMessage, json.RawMessage, error) {
	trimmedSession := strings.TrimSpace(string(session))
	if trimmedSession == "" || trimmedSession == "null" {
		session = json.RawMessage(`{"type":"realtime","model":"gpt-realtime"}`)
	}
	var clientSession map[string]any
	if errUnmarshal := json.Unmarshal(session, &clientSession); errUnmarshal != nil || clientSession == nil {
		return nil, nil, errors.New("session must be a valid JSON object")
	}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Initialize the Host via the SDK builder so the model stream bridge exists.
  2. Verify a successful host.model.execute_stream response (non-empty StreamID) before attempting stream_read.
  3. Treat this error as a programming/setup bug: do not retry, fix host construction.
Defensive patterns

Strategy: validation

Validate before calling

if streamID == "" {
    return errors.New("no open stream; cannot read")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "stream bridge is unavailable") {
    // host-side wiring failure; not retryable from the plugin
    return fmt.Errorf("host stream bridge missing: %w", err)
}

Prevention

When it happens

Trigger: Calling host.model.stream_read on a Host that was never given a model stream bridge, or invoking the RPC method on a zero-value/partially constructed Host.

Common situations: Test harnesses building a Host by hand; embedding code that skips bridge initialization; calling into a Host that is mid-shutdown.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/bf32e8eab8501aa3. Report an issue: GitHub.