Mintplex-Labs/anything-llm · error
Device not approved
Error message
Device not approved
What it means
validDeviceToken found the device by token but its approved column is false. Devices created by POST /mobile/register are not auto-approved; an admin must POST /api/mobile/update/:id with { approved: true } (approved is the only writable field). Until then every device-authenticated call returns 400 { error: 'Device not approved' }.
Source
Thrown at server/endpoints/mobile/middleware/index.js:25
* exists in the database and is approved.
* @param {import("express").Request} request
* @param {import("express").Response} response
* @param {import("express").NextFunction} next
*/
async function validDeviceToken(request, response, next) {
try {
const token = request.header("x-anythingllm-mobile-device-token");
if (!token)
return response.status(400).json({ error: "Device token is required" });
const device = await MobileDevice.get(
{ token: String(token) },
{ user: true }
);
if (!device)
return response.status(400).json({ error: "Device not found" });
if (!device.approved)
return response.status(400).json({ error: "Device not approved" });
// If the device is associated with a user then we can associate it with the locals
// so we can reuse it later.
if (device.user) {
if (device.user.suspended)
return response.status(400).json({ error: "User is suspended." });
response.locals.user = device.user;
}
delete device.user;
response.locals.device = device;
next();
} catch (error) {
console.error("validDeviceToken", error);
response.status(500).json({ error: "Invalid middleware response" });
}
}
View on GitHub (pinned to 3aec848f28)
Solutions
- Have an admin approve: POST /api/mobile/update/<device id> with body {"approved":true}
- In the mobile client, treat 'Device not approved' as a distinct 'waiting for approval' state and poll gently — do not re-register on this error
- If approval was wrongly revoked, set approved:true again via the same update endpoint
Example fix
// before — client retries instantly in a loop
while (true) await api.command('workspaces');
// after — recognize pending state and back off
const res = await api.command('workspaces');
if ((await res.json()).error === 'Device not approved') {
setStatus('awaiting_admin_approval');
await sleep(5000); // poll politely
} Defensive patterns
Strategy: retry
Try / catch
try {
await api.command('workspaces');
} catch (e) {
if (e.status === 400 && e.body?.error === 'Device not approved') {
scheduleApprovalPoll(5000); // retry with backoff until admin approves
return;
}
throw e;
} Prevention
- Design the app with an explicit 'awaiting admin approval' state
- Poll sparingly (seconds, not milliseconds) to avoid hammering the server
- Do not re-register on this error — the existing token is fine once approved
When it happens
Trigger: The app registers, saves its token, and immediately calls further /api/mobile/* endpoints before an admin approves it; or the admin sets approved back to false to revoke live access while keeping the row.
Common situations: Race between registration and approval during demos/tests; approval step missed because the flow wasn't obvious; revoke-by-unapprove used instead of delete.
Related errors
- Device not found
- Device token is required
- Device not found
- User is suspended.
- Registration token is required
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/49fc02ebeaf48aac.
Report an issue: GitHub.