hcengineering/platform · critical · Error
Failed to fetch config
Error message
Failed to fetch config
What it means
loadServerConfig fetches <server-url>/config.json, which describes service endpoints (accounts, collaborator, etc.). If the fetch response is not ok (404, 500, etc.), it throws 'Failed to fetch config'. The client cannot discover service URLs without this file.
Source
Thrown at foundations/core/packages/api-client/src/config.ts:31
// limitations under the License.
//
import { concatLink } from '@hcengineering/core'
export interface ServerConfig {
ACCOUNTS_URL: string
COLLABORATOR_URL: string
FILES_URL: string
UPLOAD_URL: string
}
export async function loadServerConfig (url: string): Promise<ServerConfig> {
const configUrl = concatLink(url, '/config.json')
const res = await fetch(configUrl, { keepalive: true })
if (res.ok) {
return (await res.json()) as ServerConfig
}
throw new Error('Failed to fetch config')
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Open <url>/config.json in a browser/curl and confirm it returns valid JSON with 200.
- Correct the base URL passed to connect/loadServerConfig.
- Check the server deployment includes config.json and the reverse proxy routes it correctly.
- Check network/DNS/CORS issues preventing the fetch.
Example fix
// before
const client = await connect('https://wrong-host.example.com', { workspace: 'ws' })
// after
const res = await fetch('https://huly.example.com/config.json')
if (!res.ok) throw new Error('config.json unreachable: ' + res.status)
const client = await connect('https://huly.example.com', { workspace: 'ws' }) Defensive patterns
Strategy: retry
Validate before calling
const res = await fetch(new URL('/config.json', baseUrl), { method: 'HEAD' })
if (!res.ok) throw new Error(`Server at ${baseUrl} is not a Huly frontend (config.json ${res.status})`) Type guard
function isServerConfig(v: unknown): v is ServerConfig {
return typeof v === 'object' && v !== null && 'ACCOUNTS_URL' in v
} Try / catch
async function loadConfigWithRetry(url: string, attempts = 3): Promise<ServerConfig> {
for (let i = 0; i < attempts; i++) {
try { return await loadServerConfig(url) }
catch (e) { if (i === attempts - 1) throw new Error(`Cannot reach ${url}/config.json — check the URL, proxy and network`, { cause: e }) ; await sleep(1000 * 2 ** i) }
}
throw new Error('unreachable')
} Prevention
- Verify <base-url>/config.json returns 200 JSON during deployment smoke tests
- Never hardcode a guessed host; keep the server URL in validated env config
- Check reverse-proxy rules preserve /config.json routing
When it happens
Trigger: Calling connect/getWorkspaceToken against a URL where /config.json is missing, returns 404, or the server is down/proxy returns an error page.
Common situations: Pointing the client at a wrong or non-Huly frontend URL, server behind a proxy that strips/rewrites config.json, deployment where static config.json was not deployed, network outage or DNS misconfiguration, CORS-blocked fetch failing the response.
Related errors
- response.statusText
- unknownError(response.statusText)
- Failed to delete file
- Failed to delete file
- Failed to delete file
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/fae7b37c5c146df0.
Report an issue: GitHub.