OtterMind/Chat2DB · critical · RuntimeError
QQ_GROUP_ID must be a numeric QQ group number
Error message
QQ_GROUP_ID must be a numeric QQ group number
What it means
Raised by RelayConfig.from_environment (relay_server.py:64) as a RuntimeError when QQ_GROUP_ID is not composed entirely of digits (str.isdigit() is false). The group id is parsed with int() and sent to OneBot, so a non-numeric value is fatal at startup.
Source
Thrown at script/github/qq_relay/relay_server.py:64
onebot_token: str
onebot_url: str
repository: str
group_id: int
max_message_length: int = 900
rate_limit: int = 30
rate_window_seconds: int = 60
@classmethod
def from_environment(cls) -> "RelayConfig":
relay_token = os.environ.get("RELAY_TOKEN", "")
onebot_token = os.environ.get("ONEBOT_TOKEN", "")
group_id = os.environ.get("QQ_GROUP_ID", "")
if len(relay_token) < 32:
raise RuntimeError("RELAY_TOKEN must contain at least 32 characters")
if len(onebot_token) < 32:
raise RuntimeError("ONEBOT_TOKEN must contain at least 32 characters")
if not group_id.isdigit():
raise RuntimeError("QQ_GROUP_ID must be a numeric QQ group number")
return cls(
relay_token=relay_token,
onebot_token=onebot_token,
onebot_url=os.environ.get("ONEBOT_URL", "http://napcat:3000"),
repository=os.environ.get("RELAY_REPOSITORY", "OtterMind/Chat2DB"),
group_id=int(group_id),
max_message_length=int(os.environ.get("RELAY_MAX_MESSAGE_LENGTH", "900")),
rate_limit=int(os.environ.get("RELAY_RATE_LIMIT", "30")),
)
class RateLimiter:
def __init__(self, limit: int, window_seconds: int):
self.limit = limit
self.window_seconds = window_seconds
self._timestamps: deque[float] = deque()
self._lock = threading.Lock()
View on GitHub (pinned to 5ee1e990e7)
Solutions
- Set QQ_GROUP_ID to the numeric QQ group number (digits only), e.g. 123456789.
- Remove any quotes, spaces, or '+' prefix from the value.
- Confirm it is a group id, not a personal QQ account.
Example fix
# before: QQ_GROUP_ID="+123456789" # after: QQ_GROUP_ID=123456789
Defensive patterns
Strategy: validation
Validate before calling
import os
group_id = os.environ.get("QQ_GROUP_ID", "")
if not group_id.isdigit():
raise SystemExit("QQ_GROUP_ID must be digits only, e.g. 123456789") Type guard
def is_numeric_group_id(value: str) -> bool:
return value.isdigit() Prevention
- Use the QQ group number (digits only), not a user QQ number.
- Strip whitespace, quotes, and '+' prefixes when setting the env var.
When it happens
Trigger: Starting the relay with QQ_GROUP_ID unset (empty string fails isdigit), containing spaces, a leading '+', or non-digit characters. Checked at startup.
Common situations: QQ_GROUP_ID copied with surrounding whitespace or quotes; the group number pasted with a prefix; the env var unset; using a QQ number (user) instead of a group number.
Related errors
- A delivery ID is required for relay deduplication
- RELAY_TOKEN must contain at least 32 characters
- ONEBOT_TOKEN must contain at least 32 characters
- The baseURL is not valid!
- The baseURL is not valid!
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/faf4955aea7132a9.
Report an issue: GitHub.