amruthpillai/reactive-resume · error · ORPCError

PRECONDITION_FAILED

PRECONDITION_FAILED

Error message

AI agent workspace is unavailable because REDIS_URL or ENCRYPTION_SECRET is not configured.

What it means

A PRECONDITION_FAILED ORPCError raised by the mapAgentEnvironmentError middleware whenever the underlying service call throws an Error whose message is exactly 'AGENT_ENVIRONMENT_UNAVAILABLE'. That inner error comes from assertAgentEnvironment (packages/api/src/features/ai/credentials.ts), which requires both env.ENCRYPTION_SECRET (for AES-256-GCM credential encryption) and env.REDIS_URL (for resumable agent streaming) to be set. The message names both because either one missing disables the whole agent workspace.

Source

Thrown at packages/api/src/features/agent/routing.ts:10

import type { AnyMiddleware } from "@orpc/server";
import type { UIMessage } from "ai";
import { ORPCError } from "@orpc/client";

function isAgentEnvironmentUnavailable(error: unknown) {
	return error instanceof Error && error.message === "AGENT_ENVIRONMENT_UNAVAILABLE";
}

function throwUnavailable(): never {
	throw new ORPCError("PRECONDITION_FAILED", {
		message: "AI agent workspace is unavailable because REDIS_URL or ENCRYPTION_SECRET is not configured.",
	});
}

export function isUiMessage(value: unknown): value is UIMessage {
	if (!value || typeof value !== "object") return false;

	const message = value as Partial<UIMessage>;
	return (
		typeof message.id === "string" &&
		(message.role === "system" || message.role === "user" || message.role === "assistant") &&
		Array.isArray(message.parts)
	);
}

// ponytail: single middleware replaces 12 near-identical try/catch blocks across agent route handlers
export const mapAgentEnvironmentError: AnyMiddleware = async ({ next }) => {
	try {

View on GitHub (pinned to 3a5b12e2a4)

Solutions

  1. Add ENCRYPTION_SECRET (any non-empty secret, ideally 32+ random bytes) and REDIS_URL (e.g. redis://localhost:6379) to .env / .env.local and restart the server.
  2. If using Turborepo, confirm both names appear in turbo.json globalEnv or the relevant task env, otherwise they will be undefined inside the spawned process even when set in the OS.
  3. Start the Redis service (docker compose up -d redis or equivalent) and confirm connectivity before retrying.
  4. Guard the UI: hide/disable agent features until GET /api/rpc/agent.health (or equivalent capability flag) reports available, so users never reach this precondition.

Example fix

# before
APP_URL=http://localhost:3000
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
AUTH_SECRET=dev-secret

# after (add the two agent env vars)
APP_URL=http://localhost:3000
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
AUTH_SECRET=dev-secret
ENCRYPTION_SECRET=__generate_32_random_bytes__
REDIS_URL=redis://localhost:6379
Defensive patterns

Strategy: validation

Validate before calling

// Call a capability/health probe before exposing agent UI.
const capable = await orpc.agent.capabilities(); // or whatever the capability route is
if (!capable.agentEnvironment) hideAgentFeatures();

Type guard

function isAgentEnvConfigured(env: { REDIS_URL?: string; ENCRYPTION_SECRET?: string }): boolean {
  return !!env.REDIS_URL?.trim() && !!env.ENCRYPTION_SECRET?.trim();
}

Prevention

When it happens

Trigger: Calling any agent route (threads.create, threads.getOrCreateForResume, messages.send, attachments.*) in a server process where REDIS_URL is unset or whitespace-only OR ENCRYPTION_SECRET is unset/whitespace; running the dev server without these in .env; deploying with Turborepo strict env mode without listing the vars in turbo.json globalEnv (so they get filtered out of child processes).

Common situations: Fresh checkout that only set APP_URL/DATABASE_URL/AUTH_SECRET (the three required vars) but never added the optional agent vars; ENCRYPTION_SECRET was set once then removed when re-deploying; REDIS_URL points at a Redis that is not started; Turborepo 2.x strict env dropped the var because it isn't declared in turbo.json.

Related errors


AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12). Data as JSON: /api/errors/43d701c22c385719. Report an issue: GitHub.