toeverything/AFFiNE · error · GraphqlBadRequest
caldav_invalid_url
caldav_invalid_url
Error message
CalDAV URL is invalid.
What it means
The CalDAV provider's assertAllowedUrl (caldav.ts) parses the user-supplied URL with new URL(); a parse failure throws GraphqlBadRequest with code caldav_invalid_url. This is the first gate before the protocol, host-allowlist, and SSRF checks run.
Source
Thrown at packages/backend/server/src/plugins/calendar/providers/caldav.ts:563
maxBytes: DEFAULT_MAX_RESPONSE_BYTES,
allowedHeaders: CALDAV_SAFE_FETCH_HEADERS,
allowedHosts: this.allowedHosts,
allowHttp: this.allowInsecureHttp,
allowPrivateTargetOrigin: !this.blockPrivateNetwork,
});
} catch (error) {
const ssrfError = this.toGraphqlSsrfError(error);
if (ssrfError) throw ssrfError;
throw error;
}
}
private async assertAllowedUrl(urlValue: string) {
let url: URL;
try {
url = new URL(urlValue);
} catch {
throw new GraphqlBadRequest({
code: 'caldav_invalid_url',
message: 'CalDAV URL is invalid.',
});
}
if (
url.protocol !== 'https:' &&
!(url.protocol === 'http:' && this.allowInsecureHttp)
) {
throw new GraphqlBadRequest({
code: 'caldav_insecure_url',
message: 'CalDAV URL must use https.',
});
}
const hostname = url.hostname.toLowerCase();
if (
this.allowedHosts.length &&View on GitHub (pinned to b4c8548c09)
Solutions
- Enter a full absolute URL including the scheme, e.g. https://caldav.example.com/user/.
- Trim whitespace and strip stray characters before submitting.
- Validate with new URL() on the client before calling the API.
Example fix
// before
await caldav.connect('caldav.example.com/user'); // no scheme -> caldav_invalid_url
// after
const url = 'caldav.example.com/user'.trim();
const normalized = /^https?:\/\//.test(url) ? url : `https://${url}`;
await caldav.connect(normalized); Defensive patterns
Strategy: validation
Validate before calling
function isValidHttpUrl(v: string): boolean {
try { new URL(v.trim()); return true; } catch { return false; }
}
if (!isValidHttpUrl(caldavUrl)) {
// show 'Enter a full URL, e.g. https://...' before calling the API
} Type guard
function isParsableUrl(v: string): v is `${'http' | 'https'}://${string}` {
try { new URL(v); return true; } catch { return false; }
} Try / catch
try { await caldav.connect(url); } catch (e) { if (e.code === 'caldav_invalid_url') showUrlFormatError(); else throw e; } Prevention
- Trim pasted input and require the scheme in the UI.
- Auto-prefix https:// when the user omits the scheme.
- Validate with new URL() client-side before submit.
When it happens
Trigger: Saving or linking a CalDAV calendar subscription with a URL that cannot be parsed — missing scheme (example.com/dav), stray whitespace or punctuation, or a bare hostname.
Common situations: User omits https:// when entering the CalDAV endpoint; copy-paste includes trailing punctuation or invisible whitespace; client sends just a hostname or a malformed user:pass@host construction.
Related errors
- caldav_insecure_url
- caldav_provider_not_found
- caldav_provider_unavailable
- ValueNotExists
- Param not a number: ${mode},${numbeToken.text}
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/ed40f28d4a53ccd6.
Report an issue: GitHub.