actualbudget/actual · error
URL not allowed: Unable to verify allowlist
Error message
URL not allowed: Unable to verify allowlist
What it means
Before checking the target against allowlist rules, the proxy fetches the latest allowlist. If fetchAllowlist() throws (e.g. the allowlist source is unreachable), the proxy conservatively refuses the request with 403 'URL not allowed / Unable to verify allowlist'. This is a fail-closed behavior: inability to verify is treated as not allowed.
Source
Thrown at packages/sync-server/src/app-cors-proxy.js:153
// Validate session/token
const session = await validateSession(req, res);
if (!session) {
return; // validateSession already sent the response
}
let url;
try {
url = new URL(targetUrlString);
} catch {
return res.status(400).json({ error: 'Invalid url parameter' });
}
// Fetch the latest allowlist
try {
await fetchAllowlist();
} catch (error) {
console.error('Failed to fetch allowlist:', error);
return res.status(403).json({
error: 'URL not allowed',
message: 'Unable to verify allowlist',
});
}
// Check if the URL is allowed
if (!isUrlAllowed(url.href)) {
console.warn('Blocked request to unauthorized URL:', url.href);
return res.status(403).json({
error: 'URL not allowed',
message:
'Only allowlisted plugin repositories are allowed (localhost only in development)',
});
}
try {
const { method = 'GET', headers: customHeaders = {} } = req.body || {};
View on GitHub (pinned to d4334cb6e6)
Solutions
- Check the sync server's outbound network access and the console error logged server-side ('Failed to fetch allowlist') for the root cause.
- Verify the allowlist source URL/configuration is correct and reachable (curl it from the server host).
- Retry after the transient outage, or host a local allowlist copy so verification does not depend on an external service.
Example fix
// before (server env with no egress) ALLOWLIST_URL=https://plugins.actualbudget.org/allowlist.json // after: serve the allowlist locally ALLOWLIST_URL=http://localhost:5006/allowlist.json
Defensive patterns
Strategy: retry
Validate before calling
const allowlistUrl = process.env.ALLOWLIST_URL;
if (allowlistUrl) {
const r = await fetch(allowlistUrl).catch(() => null);
if (!r || !r.ok) console.warn('Allowlist source unreachable; proxy requests will 403');
} Try / catch
async function proxyWithRetry(url, attempts = 3) {
for (let i = 0; i < attempts; i++) {
const res = await fetch(`/cors-proxy?url=${encodeURIComponent(url)}`);
if (res.status !== 403) return res;
await new Promise(r => setTimeout(r, 2 ** i * 1000));
}
throw new Error('Proxy could not verify allowlist (403)');
} Prevention
- Ensure the sync-server host has outbound internet access.
- Host the allowlist locally if the server runs in a restricted network.
- Monitor server logs for 'Failed to fetch allowlist' as an early warning.
When it happens
Trigger: The remote allowlist fetch fails — network outage on the server, allowlist host down, DNS failure, or invalid allowlist content — while a proxied request arrives.
Common situations: Self-hosted server without outbound internet access; allowlist URL misconfigured or moved; corporate firewall blocking the server's egress; transient upstream outage.
Related errors
- URL not allowed: Only allowlisted plugin repositories are al
- Could not resolve on-disk budget id for syncId ${syncId} aft
- results.reason || results.error_code
- results.reason || results.error
- Failed to fetch catalog: ${response.statusText}
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/c3f0cef466e24d96.
Report an issue: GitHub.