cloudflare/pingora · error · panic

Custom proxy task API not implemented

Error message

Custom proxy task API not implemented

What it means

`write_proxy_tasks` is a default method on the `Custom` session trait in pingora-core that unconditionally panics. It exists so implementors of custom protocols only pay for the proxy-task API if they use it: the default body panics with "Custom proxy task API not implemented" to signal that this custom session does not support queuing HTTP proxy tasks. The panic is documented and expected whenever the proxy-task path is exercised on a session that never overrode the method.

Source

Thrown at pingora-core/src/protocols/http/custom/server.rs:90

    ///
    /// # Panics
    /// Panics if the Custom session does not implement the proxy task API.
    #[track_caller]
    fn send_proxy_task(&mut self, _task: HttpTask) {
        panic!("Custom proxy task API not implemented")
    }

    /// Whether there are pending proxy tasks queued for writing.
    fn has_pending_proxy_tasks(&self) -> bool {
        false
    }

    /// Write queued proxy tasks in a cancel-safe manner.
    ///
    /// # Panics
    /// Panics if the Custom session does not implement the proxy task API.
    fn write_proxy_tasks(&mut self) -> impl Future<Output = Result<bool>> + Send {
        async { panic!("Custom proxy task API not implemented") }
    }

    fn set_read_timeout(&mut self, timeout: Option<Duration>);

    fn get_read_timeout(&self) -> Option<Duration>;

    fn set_write_timeout(&mut self, timeout: Option<Duration>);

    fn get_write_timeout(&self) -> Option<Duration>;

    fn set_total_drain_timeout(&mut self, timeout: Option<Duration>);

    fn get_total_drain_timeout(&self) -> Option<Duration>;

    fn request_summary(&self) -> String;

    fn response_written(&self) -> Option<&ResponseHeader>;

View on GitHub (pinned to 4487f7b2ab)

Solutions

  1. Do not drive custom-protocol sessions through the HTTP proxy-task API; handle them with the custom session's own read/write methods and return the response directly.
  2. If proxy tasks are needed, override `write_proxy_tasks` (and related proxy-task methods) in your `Custom` trait implementation with a real protocol-specific implementation.
  3. Ensure the server/handoff logic selects the HTTP session type (h1/h2) rather than the custom session type when proxy-task behavior is required.
Defensive patterns

Strategy: type-guard

Validate before calling

// Before routing a session through proxy-task APIs, confirm it is not a Custom session
fn supports_proxy_tasks(session: &Session) -> bool {
    !matches!(session.as_downstream(), /* custom protocol session */ _ if is_custom(session))
}

Type guard

fn is_custom_session(s: &Session) -> bool {
    // narrow by the concrete downstream/session enum variant for the custom protocol
    matches!(s.as_downstream(), DownstreamSession::Custom(_))
}

Prevention

When it happens

Trigger: Using a `custom` protocol session (from `pingora-core/src/protocols/http/custom/server.rs`) in a context that calls `write_proxy_tasks` — e.g., routing a custom-protocol connection through HTTP proxy task writing — without the trait implementor overriding `write_proxy_tasks` with a real implementation.

Common situations: Configuring a Pingora app with a custom protocol listener but letting the generic proxy pipeline (which expects HTTP proxy tasks) drive the session; upgrading Pingora and new proxy-task code paths now reaching the custom session default; implementing `Custom` for a protocol that has no notion of HTTP proxy tasks and then using it with `proxy_to_upstream`-style APIs.

Related errors


AI-assisted analysis of cloudflare/pingora@4487f7b2ab (2026-09-13). Data as JSON: /api/errors/38668895786ad471. Report an issue: GitHub.