Skip to content

Troubleshooting

Common problems

Multiple decisions for the same request

If you are seeing multiple decisions for the same request, it is likely that Arcjet is running in multiple places in your application. This can happen if you are using a middleware and also calling the Arcjet SDK in a route handler.

You can fix this by ensuring that Arcjet is only called once per request. You can combine multiple rules into a single client configuration and/or you can exclude routes from your middleware.

Decision errors from platform liveness or health checks when using Arcjet as a middleware

Platforms like Kubernetes have support for automatic liveness and health check probes. These requests do not come from a browser and do not have all the same metadata that browsers do (and will not include important headers like X-Real-Ip or X-Forwarded-For). This will cause Arcjet to reject these probes, which will make the platform think your app is either not alive or unhealthy. This can manifest in CrashLoopBackoff errors in Kubernetes or your platform of choice restarting your app constantly.

In order to fix this, omit your healthcheck route from your Arcjet middleware.

Next.js

Assuming you have your Arcjet middleware at middleware.ts, adjust the config.matcher regex to include an omission for the /healthz route:

export const config = {
// matcher tells Next.js which routes to run the middleware on.
// This runs the middleware on all routes except for static assets.
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
matcher: ["/((?!_next/static|_next/image|favicon.ico|healthz).*)"],
};

Then create an API route at /app/healthz/route.ts:

app/healthz/route.ts
import { NextRequest, NextResponse } from "next/server";
export const GET = async (req: NextRequest) => {
if (req.headers.get("user-agent") !== "healthz") {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
return new Response("OK", {
status: 200,
headers: {
"Content-Type": "text/plain",
},
});
};

When you deploy your app next, Arcjet should not trigger on this route.

Common errors

[unauthenticated] invalid key

✦Aj Encountered problem getting remote decision: [unauthenticated] invalid key

This error means that the Arcjet key you are using is invalid. Each site has a unique key to identify it within Arcjet. You can find your key in the Arcjet dashboard by clicking your site name and then going to the SDK installation tab.

Arcjet keys are always prefixed with ajkey_

You provide the Arcjet SDK with the key when instantiating the client. For example in this case the key is defined in an environment variable called ARCJET_KEY:

import arcjet from "arcjet";
const aj = arcjet({
// Get your site key from https://app.arcjet.com
// and set it as an environment variable rather than hard coding.
// See: https://www.npmjs.com/package/dotenv
key: process.env.ARCJET_KEY,
rules: [
// Protect against common attacks with Arcjet Shield
shield({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
}),
],
});

[deadline_exceeded] the operation timed out

✦Aj Encountered problem getting remote decision: [deadline_exceeded] the operation timed out
ConnectError: [deadline_exceeded] the operation timed out

This error means that the Arcjet SDK was unable to connect to the Arcjet API within the short timeout period. This is usually caused by a network issue. The SDK is designed to fail open so that in the event of a network problem or outage, requests will be allowed.

If you are seeing this error frequently, please contact us so we can investigate.

generateFingerprint: ip is empty / [failed_precondition] client IP not provided

Arcjet normally detects when it is running in a local environment and uses a default IP address of 127.0.0.1. However, if it can’t determine whether it is running locally or not then it will be safe and assume it is running in production. In production environments we disallow private/internal addresses, but they are allowed in development to allow you to test locally.

You can force the SDK to run in development mode by setting the environment variable ARCJET_ENV to development in your .env.local file:

.env.local
ARCJET_ENV=development

Arcjet uses the client IP address as part of a fingerprint to identify where each request is coming from. If the IP address is not provided, or it is running in production and a private/internal address is provided, then Arcjet will show this error.

[failed_precondition] request details failed validation

Arcjet expects certain fields to exist on the object used to analyze each request. This is normally handled by the SDK for the framework you are using, but if you are doing something custom then you will need to provide the correct fields:

The required fields are:

  • ip - The client IP address. Internally our SDKs use our @arcjet/ip package to detect the correct IP which you can also use directly.
  • method - The HTTP method of the request.
  • host - The host of the request.
  • path or url - The path of the request. In the Node.js SDK this field is called url. If you are not using an adapter, this is called path.
  • headers - The headers of the request.

Property ‘[INTERNALS]’ is missing in type

When using the Arcjet Next.js SDK you may see a warning in your editor like this:

Argument of type x is not assignable to parameter of type 'NextMiddleware'.
Types of parameters 'req' and 'request' are incompatible.
Property '[INTERNALS]' is missing in type 'import(".../next/dist/server/web/spec-extension/request").NextRequest' but required in type 'import(".../next/dist/server/web/spec-extension/request").NextRequest'.ts(2345)
request.d.ts(7, 5): '[INTERNALS]' is declared here.

This is usually caused by a mismatch between the version of Next.js you are using and the version of the Arcjet SDK. You have several options for fixing this:

  1. Update the Arcjet SDK to the latest version and update your version of Next.js to the latest version. We try to keep the SDK up to date with the latest Next.js releases so they should generally match.

  2. Add a resolution override to your package.json to force the SDK to use the same version of Next.js. For example, if you are using Next.js 14.1.4 you can add this override to your package.json to force the Arcjet SDK to use the same version:

    {
    "overrides": {
    "next": "14.1.4"
    }
    }
  3. You can ignore the warning. The warning is just a TypeScript error and does not affect the runtime behavior of your application. You can add a comment on the line that is causing the error to ignore it: // @ts-ignore

Calling protect() with no rules is deprecated

When using the Arcjet SDK you may see a warning like this:

Calling `protect()` with no rules is deprecated. Did you mean to configure the Shield rule?

Prior to the JS SDK release v1.0.0-alpha.12 we allowed empty rules and automatically configured a Shield rule for you. From v1.0.0-alpha.12 onwards you must explicitly configure the Shield rule. This allows you to choose if you want to block suspicious requests or not. We are maintaining the old behavior for a while to give you time to update your code, which is why this is warning you. Shield is still configured automatically but you should now migrate to explicitly configuring it.

Check out the Shield documentation to learn how to configure Shield rules. To restore the old behavior you can add a simple Shield rule:

import arcjet, { shield } from "@arcjet/next";
const aj = arcjet({
// Get your site key from https://app.arcjet.com
// and set it as an environment variable rather than hard coding.
// See: https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables
key: process.env.ARCJET_KEY,
rules: [
// Protect against common attacks with Arcjet Shield
shield({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
}),
],
});

The current file is a CommonJS module whose imports will produce ‘require’ calls

When using the Arcjet SDK you may see a warning like this:

The current file is a CommonJS module whose imports will produce 'require'
calls; however, the referenced file is an ECMAScript module and cannot be
imported with 'require'.

This warning is caused by a mismatch between the module system used by the Arcjet SDK and the module system used by your application. The Arcjet SDK uses ECMAScript modules (ESM) but your application is using CommonJS modules (CJS).

The Arcjet SDK does not support CJS. You can fix this by changing your application to use ESM. This is usually done by adding "type": "module" to your package.json.

Alternatively, you can rename the files where you are using the Arcjet SDK to use the .mjs or .mts extension. This will tell Node.js to treat the file as an ESM file.

Error: Log is required / Error: Client is required

You may see an error like this:

Error: Log is required
at arcjet (/node_modules/arcjet/index.js:520:15)
...
Error: Client is required
at arcjet (/node_modules/arcjet/index.js:526:15)

This error usually means that you are trying to use the base arcjet package rather than an adapter. You probably meant to use the @arcjet/node package instead.

The arcjet package is a low-level package that is used to build adapters for different frameworks and runtimes we support. Unless you are doing something custom, we recommend using one of the adapters.

Error: Body already read or Body is unusable

You may see this error if you try to access the request body after it has already been read by something else.

For example, if Arcjet processes the body to analyze it for sensitive information and then you try and access the body later in your handler.

Another example is if you access a field in the body to perform email validation and then later try to access the body again in another part of your request handler.

To fix this with sensitive information detection, see the Accessing the body section of the reference.

To fix this with other cases, clone the request before accessing the body:

// Clone the request and extract the email
const { email } = await req.clone().json();
// Call Arcjet with the cloned request
const decision = await aj.protect(req, { email });
// ...
// You can now access the body again later

Get help

We provide technical support for all Arcjet users so if you need help, email us or join our Discord.

Discussion