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

  1. Restart the kernel without --readonly if writes are intended.
  2. If read-only is intentional, configure the WebDAV client to mount read-only / disable sync writes.
  3. 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

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


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/8eb8030bd01dd939. Report an issue: GitHub.