yikart/AiToEarn · error · AppException
InvalidWorkLink
InvalidWorkLink
Error message
ResponseCode.InvalidWorkLink
What it means
BilibiliWorkProvider.getLinkInfo normalizes the given work link and tries to extract a Bilibili video ID (BV/av). If parseVideoId returns null the link is not a recognizable Bilibili video URL, so it throws AppException InvalidWorkLink.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/bilibili/bilibili-work.provider.ts:16
import type { ChannelWorkDataResult, WorkLinkInfoInput, WorkProvider } from '../platforms.interface'
import { Injectable, Logger } from '@nestjs/common'
import { PublishType } from '@yikart/aitoearn-server-shared'
import { AccountType, AppException, ResponseCode } from '@yikart/common'
import axios from 'axios'
@Injectable()
export class BilibiliWorkProvider implements WorkProvider {
readonly requiresCredentialForLinkInfo = false
private readonly logger = new Logger(BilibiliWorkProvider.name)
async getLinkInfo(input: WorkLinkInfoInput): Promise<ChannelWorkDataResult> {
const resolvedUrl = await this.normalizeLink(input.link)
const dataId = this.parseVideoId(resolvedUrl)
if (!dataId) {
throw new AppException(ResponseCode.InvalidWorkLink)
}
const url = `https://www.bilibili.com/video/${dataId}`
return {
snapshots: [],
work: {
id: dataId,
url,
mediaType: PublishType.VIDEO,
},
extra: {
dataId,
uniqueId: `${AccountType.Bilibili}_${dataId}`,
type: PublishType.VIDEO,
videoType: 'long',
resolvedUrl: url,
},
rawResponse: { resolvedUrl },View on GitHub (pinned to d3aa8bea5b)
Solutions
- Validate the URL resolves to a /video/BV... or /video/av... path before calling getLinkInfo.
- Ask the user to paste the canonical video URL (www.bilibili.com/video/BV...).
- Update normalizeLink/parseVideoId regexes if Bilibili introduced new valid URL formats.
- Catch InvalidWorkLink and return 'this link is not a Bilibili video' to the caller.
Example fix
// before
await workProvider.getLinkInfo({ link: 'https://www.bilibili.com/space/xyz' })
// after
const m = link.match(/bilibili\.com\/video\/(BV[\w]+|av\d+)/)
if (!m) throw new InvalidWorkLink()
await workProvider.getLinkInfo({ link }) Defensive patterns
Strategy: validation
Validate before calling
const VIDEO_RE = /^https?:\/\/(www\.)?bilibili\.com\/video\/(BV[\w]+|av\d+)/i
if (!VIDEO_RE.test(link) && !/^https?:\/\/b23\.tv\//.test(link)) {
throw new Error('Not a Bilibili video link')
} Type guard
function isBilibiliVideoUrl(url: string): boolean {
return /bilibili\.com\/video\/(BV[\w]+|av\d+)/i.test(url)
} Try / catch
try {
info = await workProvider.getLinkInfo({ link })
} catch (e) {
if (e.code === 'InvalidWorkLink') return { error: '请粘贴 B 站视频链接(/video/BV...)' }
throw e
} Prevention
- Validate/normalize the URL client-side before submitting
- Accept both canonical and b23.tv short links; resolve shorts first
- Keep parseVideoId regexes updated with Bilibili URL formats
When it happens
Trigger: getLinkInfo called with a link that, after normalizeLink/redirect resolution, does not match Bilibili video URL patterns (no BVxxx/avxxx ID), e.g. a space/album/article/live URL or an unrelated site URL.
Common situations: User pastes a mobile share link whose redirect target is not a video page; URL contains b23.tv short link that resolves to a non-video page; malformed/truncated URL; platform changed URL format.
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/f5f6fc956be49aa0.
Report an issue: GitHub.