siyuan-note/siyuan · warning
This operation is not supported in read-only mode
Error message
This operation is not supported in read-only mode
What it means
Returned (HTTP 403) by the WebDAV route when util.ReadOnly is enabled and the request uses a write/mutating method (POST, PUT, DELETE, MKCOL, COPY, MOVE, LOCK, UNLOCK, PROPPATCH). The message comes from model.Conf.Language(34) — the localized 'read-only mode' string. This is intentional gating, not a bug.
Source
Thrown at kernel/server/serve.go:1578
// logging.LogDebugf("WebDAV [%s %s]", r.Method, r.URL.String())
},
}
ginGroup := ginServer.Group("/webdav", model.CheckAuth, model.CheckAdminRole)
// ginGroup.Any NOT support extension methods (PROPFIND etc.)
ginGroup.Match(WebDavMethods, "/*path", func(c *gin.Context) {
if util.ReadOnly {
switch c.Request.Method {
case http.MethodPost,
http.MethodPut,
http.MethodDelete,
MethodMkCol,
MethodCopy,
MethodMove,
MethodLock,
MethodUnlock,
MethodPropPatch:
c.AbortWithError(http.StatusForbidden, errors.New(model.Conf.Language(34)))
return
}
}
handler.ServeHTTP(c.Writer, c.Request)
})
}
func serveCalDAV(ginServer *gin.Engine) {
// REF: https://github.com/emersion/hydroxide/blob/master/carddav/carddav.go
handler := caldav.Handler{
Backend: &model.CalDavBackend{},
Prefix: model.CalDavPrincipalsPath,
}
ginServer.Match(CalDavMethods, "/.well-known/caldav", func(c *gin.Context) {
// logging.LogDebugf("CalDAV -> [%s] %s", c.Request.Method, c.Request.URL.String())
handler.ServeHTTP(c.Writer, c.Request)
})View on GitHub (pinned to 251596fc0d)
Solutions
- Restart the kernel without --readonly if writes are intended.
- If read-only is intentional, configure the WebDAV client to mount read-only / disable sync writes.
- Verify the access mode in Settings - About / startup flags and remove the read-only switch.
Example fix
// before kernel --serve --readonly // after kernel --serve
Defensive patterns
Strategy: validation
Validate before calling
// Client side: probe capabilities before issuing writes.
async function canWriteWebDAV(base: string, auth: string): Promise<boolean> {
const r = await fetch(`${base}/webdav/`, { method: 'OPTIONS', headers: { Authorization: auth } })
// If server advertises read-only or returns 403 on PROPFIND write-class, treat as read-only.
return !r.headers.get('allow')?.toUpperCase().includes('READONLY')
} Try / catch
// Handle 403 gracefully and surface a clear message.
try { await webdavPut(...) }
catch (e) {
if (e.status === 403) console.warn('workspace is read-only; write skipped')
else throw e
} Prevention
- Do not start the kernel with --readonly unless you intend to block writes.
- Mount WebDAV read-only in clients when the workspace is read-only.
- Document the read-only flag so operators remember to turn it off after maintenance.
When it happens
Trigger: A WebDAV client (Finder, Windows Explorer, Cyberduck) issues PUT/MKCOL/MOVE/etc. against /webdav/* while the kernel is running in read-only mode (--readonly flag or config).
Common situations: Kernel started with --readonly for a demo/preview; user mounted the workspace read-only intentionally; config flip forgotten after maintenance; sync/backup drive running read-only.
Related errors
- This operation is not supported in read-only mode
- unsupported server type: %s
- command is required for stdio server
- start command: %w
- no AI provider configured
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/8eb8030bd01dd939.
Report an issue: GitHub.