yikart/AiToEarn · warning · AppException
ResponseCode.ChannelAuthSelectionRequired
ResponseCode.ChannelAuthSelectionRequired
Error message
ChannelAuthSelectionRequired
What it means
Thrown in AuthService.saveSelectedAccountsForUser when the submitted selectedAccounts array is empty. Persisting the user's chosen second-level accounts requires at least one account identity ({ platformUid, account? }); an empty submission means nothing was selected.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/auth/auth.service.ts:327
allowReassign?: boolean
}): Promise<{ accountIds: string[], accounts: ConnectedSelectableAccount[] }> {
const result = await this.saveSelectedAccountsForUser(input)
await Promise.all(result.accounts.map(account => this.emitAccountConnected(input.userId, account.accountId, account.platform, input.source)))
return result
}
@Transactional()
private async saveSelectedAccountsForUser(input: {
userId: string
platform: AccountType
selectableAccounts: PlatformSelectableAccount[]
selectedAccounts: SelectedAccountIdentity[]
groupId?: string
source: string
allowReassign?: boolean
}): Promise<{ accountIds: string[], accounts: ConnectedSelectableAccount[] }> {
if (input.selectedAccounts.length === 0) {
throw new AppException(ResponseCode.ChannelAuthSelectionRequired)
}
const keyOf = (account: SelectedAccountIdentity) => `${account.platformUid}\u0000${account.account ?? ''}`
const selectedAccounts = Array.from(
new Map(input.selectedAccounts.map(account => [keyOf(account), account])).values(),
)
const selectableAccounts = new Map(
input.selectableAccounts.map(account => [keyOf(account), account]),
)
const unknownAccount = selectedAccounts.find(account => !selectableAccounts.has(keyOf(account)))
if (unknownAccount) {
throw new AppException(ResponseCode.ChannelAuthSelectedAccountUnavailable)
}
const groupId = await this.resolveGroupId(input.userId, input.groupId)
const accountIds: string[] = []
const accounts: ConnectedSelectableAccount[] = []
View on GitHub (pinned to d3aa8bea5b)
Solutions
- Enforce at least one selection in the UI (disable submit until a checkbox is ticked) and validate client-side before POSTing.
- Reject empty arrays at the DTO boundary with a Zod min-length constraint so callers get a clear 400-style message.
- Check the frontend form serialization — ensure the accounts field is populated from the selection checkboxes.
- If the user legitimately wants to select none, cancel the flow instead of submitting an empty selection.
Example fix
// before: DTO allows empty array accounts: z.array(selectedAccountSchema) // after: require at least one selection accounts: z.array(selectedAccountSchema).min(1)
Defensive patterns
Strategy: validation
Validate before calling
function canSubmitSelection(selected: SelectedAccountIdentity[]): boolean {
return Array.isArray(selected) && selected.length > 0
}
if (!canSubmitSelection(collectedSelections)) {
alert('Select at least one account')
return
} Type guard
function hasSelections(v: unknown): v is SelectedAccountIdentity[] {
return Array.isArray(v) && v.length > 0 && v.every(i => typeof (i as any).platformUid === 'string')
} Try / catch
try {
await submitSelections(selected)
}
catch (e) {
if (getErrorCode(e) === ResponseCode.ChannelAuthSelectionRequired) {
showError('Please select at least one account before continuing')
}
} Prevention
- Require at least one checkbox before enabling submit
- Enforce z.array(...).min(1) in the selection DTO
- Verify form serialization maps checkboxes to the accounts field
- Offer an explicit cancel action instead of empty submits
When it happens
Trigger: saveSelectedAccountsForUser (via connectSelectableAccounts / connectSelectedAccountsForUser, e.g. POST /accounts/auth/selections) with body.accounts = [] — an empty selection form, a frontend bug sending no accounts, or an API caller omitting the accounts list.
Common situations: User submits the account-selection page without ticking any checkbox; frontend not mapping the checkbox values into the request body; DTO accepting an empty array because the schema only validates item shape, not min length; scripted calls to the endpoint with an empty payload.
Related errors
- imageSize must be one of 1K, 2K, or 4K
- Zod validation error (issues + input)
- 参数验证失败:
- No subtitle entries in response
- No response from Gemini
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/b14831ebbfcbf53d.
Report an issue: GitHub.