mem0ai/mem0 · critical · NodeOperationError
At least one message is required
Error message
At least one message is required
What it means
A RuntimeError raised at module import time of server/main.py: JWT-based authentication is compiled in unless AUTH_DISABLED=true, and it requires the JWT_SECRET env var to sign/verify tokens. If AUTH_DISABLED is falsy and JWT_SECRET is empty/unset, the server refuses to boot with this message rather than running with an insecure default secret.
Source
Thrown at integrations/n8n-nodes-mem0/nodes/Mem0/Mem0.node.ts:405
// First-party usage attribution: the backend reads `source` (same as OpenClaw).
qs: { source: 'N8N', ...(qs ?? {}) },
};
return (await this.helpers.httpRequestWithAuthentication.call(
this,
'mem0Api',
options,
)) as IDataObject;
};
for (let i = 0; i < items.length; i++) {
try {
const operation = this.getNodeParameter('operation', i) as string;
let responseData: IDataObject | IDataObject[] = {};
if (operation === 'add') {
const messagesUi = this.getNodeParameter('messages.message', i, []) as IDataObject[];
if (!messagesUi.length) {
throw new NodeOperationError(this.getNode(), 'At least one message is required', {
itemIndex: i,
});
}
const addFields = this.getNodeParameter('addFields', i, {}) as IDataObject;
const body: IDataObject = {
messages: messagesUi.map((m) => ({ role: m.role, content: m.content })),
infer: addFields.infer !== undefined ? addFields.infer : true,
};
const userId = this.getNodeParameter('userId', i, '') as string;
if (userId) body.user_id = userId;
if (addFields.agent_id) body.agent_id = addFields.agent_id;
if (addFields.app_id) body.app_id = addFields.app_id;
if (addFields.run_id) body.run_id = addFields.run_id;
if (addFields.metadata) {
try {
body.metadata =
typeof addFields.metadata === 'string'
? JSON.parse(addFields.metadata as string)View on GitHub (pinned to 001c235229)
Solutions
- Generate a strong secret and set it: JWT_SECRET=$(openssl rand -base64 48) in server/.env (or the container environment), then restart.
- For purely local development you may set AUTH_DISABLED=true instead — never in production or on a network-reachable host.
- If using Docker Compose, ensure the env var is passed (environment: or env_file:) to the api service and the .env file is actually mounted.
- Verify with: docker exec <container> printenv JWT_SECRET (name only — do not log the value).
Example fix
# before (.env) POSTGRES_URL=... # after (.env) POSTGRES_URL=... JWT_SECRET=<output of: openssl rand -base64 48>
Defensive patterns
Strategy: validation
Validate before calling
import os, secrets
def require_jwt_secret() -> str:
secret = os.environ.get("JWT_SECRET", "").strip()
if not secret and os.environ.get("AUTH_DISABLED", "").lower() != "true":
secret = secrets.token_urlsafe(48) # dev-only fallback; persist it or boot fails next time
if not secret:
raise RuntimeError("JWT_SECRET missing and AUTH_DISABLED!=true")
return secret Prevention
- Add JWT_SECRET to the deployment checklist alongside DB credentials.
- Use 'openssl rand -base64 48' to generate; store in a secret manager.
- Container healthcheck should fail fast on missing critical env vars.
When it happens
Trigger: Starting the FastAPI server (python main.py, uvicorn, or the Docker container) without JWT_SECRET in the environment/.env and without AUTH_DISABLED=true. Typical after cloning the repo, copying .env.example incompletely, or running a minimal docker run that only passes DB vars.
Common situations: First self-hosted deployment; CI pipeline that only sets POSTGRES_* variables; upgrading to a server version that introduced mandatory JWT_SECRET; .env file not mounted into the container so the var never reaches the process.
Related errors
- Resource not found: ${path}
- Authentication failed. Your API key may be invalid or expire
- Bad request to ${path}: ${detail}
- HTTP ${resp.status}: ${detail}
- Either memoryId or --all is required
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/e1357d9e1d140516.
Report an issue: GitHub.