Open Source API Gateway

500 Internal Server Error: Template Expression Failed

Membrane API Gateway returns 500 Internal Server Error with the line of the template when an expression in the template of the template plugin fails while it is rendered. The template belongs to the gateway configuration, even when the content of the current message triggered the error.

The Error Response

The response contains the status 500 Internal Server Error, the title Internal server error., the problem type https://membrane-api.io/problems/internal, a link to this page and the fields line and message, which contain the template line and the template error with context. For a missing variable or property, the field property names it, and for a missing method, the field method. The detail holds the message of the root cause. The type internal means that the gateway could not complete the processing of the exchange. The plugin can fail in the request or the response flow. In both cases the client receives 500.

How the Template Plugin Renders Templates

The template plugin renders a Groovy template from src or location into the message body. Inside ${…} and <% … %>, the template can use variables such as json, params, header, property and message. For text and JSON templates, a failing expression is reported with this error and the template line.

Common Causes

A Variable or Property Does Not Exist

The response carries property. Typical cases are a typo, json.x when the body is not valid JSON, because the json variable is not created then, and params in the response flow or when the query string could not be parsed.

A Method Does Not Exist

The template calls a method that the object does not have. The response carries method.

Another Error in the Expression

For any other error, for example a NullPointerException on a missing header or a division by zero, detail holds the message of the root cause.

How to Fix It

  1. Use line, property, method and detail from the response, or the warn log line, to find the failing expression.
  2. Correct the template, or make the expression null-safe with ?. and ?:.
  3. If the template expects JSON input, validate the body first, for example with an OpenAPI document, so that clients get a 400 instead of this 500.

A template that tolerates a missing query parameter:

api:
port: 2000
flow:
- request:
- template:
contentType: text/plain
src: |
Hello ${params.name?[0] ?: 'stranger'}!

- return:
status: 200
api:
  port: 2000
  flow:
    - request:
        - template:
            contentType: text/plain
            src: |
              Hello ${params.name?[0] ?: 'stranger'}!
    - return:
        status: 200

Hide Details in Production

By default, Membrane runs in development mode and adds details to error responses that help you find the problem. These details may reveal information about your setup. In production, turn them off:

configuration:
production: true
configuration:
  production: true

Add the configuration document to your apis.yaml and separate it from the APIs with ---. The title then reads Internal Server Error, and the detail and the link to this page are left out. This error does not add a log key to the response, so look for the log entries at the time of the request.

The fields line, message, property and method of this error are currently sent in production mode too, so the response can still show parts of the template and the error message. Fix failing templates rather than relying on production mode to hide them.

Related Documentation

Configuration reference:

Tutorials with runnable examples:

← All Membrane error messages

Still stuck? See the troubleshooting guide or ask on GitHub Issues. For commercial support, contact info@predic8.de.