siyuan-note/siyuan · error

invalid publish service token

Error message

invalid publish service token

What it means

ErrInvalidPublishServiceToken is the sentinel error returned when a JWT presented as a publish-service token fails validation (IsValidPublishServiceToken returns false during ParseJWT). Publish-service tokens are issued for the publish feature's accounts; once a publish account is (re)initialized the old signing context no longer validates, so tokens signed under the stale account are rejected.

Source

Thrown at kernel/model/auth.go:80

	// publishSessionTTL 发布服务会话空闲过期时长,超过后需要重新认证
	publishSessionTTL = 7 * 24 * time.Hour
	// publishSessionGlobalCap 发布服务会话全局上限,超出后淘汰最久未活跃的会话
	publishSessionGlobalCap = 4096
	// publishSessionPerAccountCap 单账户会话上限,超出后淘汰该账户最久未活跃的会话
	publishSessionPerAccountCap = 32
)

var (
	accountsMap  = AccountsMap{}
	accountsLock = sync.RWMutex{}
	sessionsMap  = map[string]*PublishSession{}
	sessionLock  = sync.Mutex{}

	jwtKey     = make([]byte, 32)
	jwtKeyOnce sync.Once

	ErrInvalidPublishServiceToken = errors.New("invalid publish service token")
)

func InitJwtKey() {
	jwtKeyOnce.Do(func() {
		err := refreshJwtKey()
		if err != nil {
			logging.LogFatalf(logging.ExitCodeFatal, "initialize JWT signing key failed: %s", err)
		}
	})
}

func refreshJwtKey() error {
	if _, err := rand.Read(jwtKey); err != nil {
		logging.LogErrorf("generate JWT signing key failed: %s", err)
		return err
	}
	return nil
}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Re-authenticate against the publish service to obtain a fresh token and retry the request
  2. Check whether the publish account was re-initialized; update clients with the new account/token
  3. Verify the token's claims and expiry are intact and match the current publish account configuration

Example fix

// before
token := cachedPublishToken // issued before account re-init
claims, err := ParseJWT(token)
// after
token := cachedPublishToken
if _, err := ParseJWT(token); errors.Is(err, ErrInvalidPublishServiceToken) {
    token = reloginPublishService() // fetch a fresh token
}
claims, err := ParseJWT(token)
Defensive patterns

Strategy: try-catch

Validate before calling

let valid = true;
try { ParseJWT(token); } catch (e) { valid = !errors.Is(e, ErrInvalidPublishServiceToken); }

Try / catch

claims, err := ParseJWT(token)
if errors.Is(err, ErrInvalidPublishServiceToken) {
    token = refreshPublishServiceToken() // re-login and retry once
    claims, err = ParseJWT(token)
}

Prevention

When it happens

Trigger: Calling ParseJWT on a token where IsPublishServiceToken(token) is true but IsValidPublishServiceToken fails — e.g. the token was issued for a publish account that was later re-initialized, the token's account credentials no longer match, or the token is malformed/expired relative to the publish account state.

Common situations: A publish account was re-created or its password reset, invalidating previously issued JWTs still held by clients; stale tokens cached in a client after the publish service was reconfigured; clock skew or expiry making the publish token invalid.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/b1555bda9ba9eae3. Report an issue: GitHub.