The built-in vcl_error subroutine is executed when explicitly triggered by an error statement (or return(error)) in vcl_recv, vcl_hit, vcl_miss, vcl_pass, or vcl_fetch, or automatically by Fastly under the following situations:

  • a semantically invalid response or timeout is encountered when Fastly attempts to make a request to a backend server
  • Fastly is unable to negotiate a connection to the backend that is acceptable to both parties (often due to incompatible TLS configurations or expired certificates)
  • the backend has reached its maximum configured number of concurrent connections
  • the backend is unhealthy

Receiving a response from a backend that has an 'error' response status, such as a 500 Internal Server Error will not trigger the vcl_error subroutine, since a 500 response status is syntactically valid. In this case Fastly will simply treat this as a normal response object and will run vcl_fetch.

Typically, triggering an error explicitly using the error statement is a way to signal that you want to return a synthetic response, instead of one from cache or a backend server.

IMPORTANT: If there is an active response object (such as resp or beresp) at the moment an error is triggered, it will be lost. When vcl_error begins, a new response object (obj) is created, which will become resp when vcl_error transitions to vcl_deliver.

Triggering error in vcl_recv will pass control to vcl_hash and then to vcl_error, while all other subroutines in which error is a valid return state will invoke vcl_error immediately. This is because the vcl_error subroutine operates on a cache object, albeit a synthetic one created by Fastly, and that object is created after the hash state.

Within this subroutine, the obj.status and obj.response variables provide information about the nature of the error. Errors generated by Fastly have a 503 status code and can be differentiated based on the obj.response text.

HINT: When triggering errors from other parts of your VCL, we recommend using a status code in the 6xx range. Numbers lower than 600 are reserved by HTTP standards and those above 700 are used by Fastly for internal signaling.

Synthetic responses

The synthetic and synthetic.base64 statements can be used in vcl_error to create a response body to send back to the client. vcl_error is the only place in VCL where a response body can be constructed. To learn more about constructing responses at the edge in vcl_error, see the error statement.


Since an error may be triggered at multiple stages of the VCL lifecycle, it is possible for the vcl_error subroutine to be invoked on either of the delivery node or the fetch node, for requests where clustering is enabled.

State transitions


To see this subroutine in the context of the full VCL flow, see using VCL.


The code example Replace origin errors with 'safe' responses is a good example of the vcl_error subroutine in use:

Tokens available in this subroutine

The following limited-scope VCL functions and variables are available for use in this subroutine (those in bold are available only in this subroutine, those available in *all* subroutines are not listed):