OtterMind/Chat2DB · error · BusinessException

largeCellValue.tokenForbidden

largeCellValue.tokenForbidden

Error message

largeCellValue.tokenForbidden

What it means

Thrown by DbLargeValueTokenServiceImpl.validateOwner when the token's userId or organizationId does not match the current Context (context.getLoginUser().getId() / context.getOrganizationId()). Tokens are scoped to the user+org that triggered the result render, so a mismatch is treated as unauthorized access. Resolves to 'You do not have permission to access this large value'. This is an authorization boundary.

Solutions

  1. Only request large values for cells rendered in the current user's own session.
  2. Ensure ContextUtils.queryContext() carries a valid LoginUser before calling requireValid.
  3. Do not share largeValueId values between users; they are per-user opaque references.
Defensive patterns

Strategy: validation

Validate before calling

Context ctx = ContextUtils.queryContext();
LoginUser u = ctx == null ? null : ctx.getLoginUser();
if (u == null || u.getId() == null) {
    // require login before large-value access
}

Type guard

boolean tokenOwnedByCaller(LargeValueToken t) {
    Context c = ContextUtils.queryContext();
    LoginUser u = c == null ? null : c.getLoginUser();
    Long uid = u == null ? null : u.getId();
    Long oid = c == null ? null : c.getOrganizationId();
    return Objects.equals(t.getUserId(), uid) && Objects.equals(t.getOrganizationId(), oid);
}

Prevention

When it happens

Trigger: One user attempting to read a large-cell token issued to another user; an organization mismatch (multi-tenant); a token id leaked/replayed in a different session; context not set so both ids resolve to null but the token was issued under a real user.

Common situations: Shared/copy-pasted URLs containing a largeValueId across users; a session that lost its login context (both ids null) trying to read a user-bound token; cross-tenant token reuse.

Understand the failure class

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/06ac96208cf4c638. Report an issue: GitHub.

Appendix: source

Thrown at chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbLargeValueTokenServiceImpl.java:154

                .primaryKey(primaryKey)
                .userId(userId)
                .organizationId(organizationId)
                .expiresAt(Instant.now().plus(DEFAULT_TTL))
                .valueType(cell.getValueType())
                .sqlType(cell.getSqlType())
                .columnType(cell.getColumnType())
                .sizeBytes(cell.getSizeBytes())
                .sizeChars(cell.getSizeChars())
                .build();
    }

    private void validateOwner(LargeValueToken token) {
        Context context = ContextUtils.queryContext();
        Long organizationId = context == null ? null : context.getOrganizationId();
        LoginUser loginUser = context == null ? null : context.getLoginUser();
        Long userId = loginUser == null ? null : loginUser.getId();
        if (!Objects.equals(token.getUserId(), userId) || !Objects.equals(token.getOrganizationId(), organizationId)) {
            throw new BusinessException("largeCellValue.tokenForbidden");
        }
    }

    private Object getLocatorValue(ResultCell cell) {
        return cell.getRawValue() == null ? cell.getValue() : cell.getRawValue();
    }
}

View on GitHub (pinned to 5ee1e990e7)