{"record":{"id":"8aae9d39cf5f488c","repo":"koala73/worldmonitor","slug":"expected-an-alphanumeric-callsign-of-at-most-eight","errorCode":null,"errorMessage":"Expected an alphanumeric callsign of at most eight characters","messagePattern":"Expected an alphanumeric callsign of at most eight characters","errorType":"validation","errorClass":"ApiError","httpStatus":400,"severity":"warning","filePath":"server/worldmonitor/aviation/v1/track-aircraft.ts","lineNumber":122,"sourceCode":"    }\n    return 'aviation:track:all:v2';\n}\n\n// Response-level source values (TrackAircraftResponse.source):\n//   'opensky'           — data from OpenSky via relay\n//   'wingbits'          — data from Wingbits via relay\n//   'none'              — all real sources returned empty or failed; positions = []\nexport async function trackAircraft(\n    ctx: ServerContext,\n    req: TrackAircraftRequest,\n): Promise<TrackAircraftResponse> {\n    const rawIcao24 = req.icao24 ?? '';\n    const rawCallsign = req.callsign ?? '';\n    if (rawIcao24.length > 16 || rawCallsign.length > 16) throw new ApiError(400, 'Aircraft identifier is too long', '');\n    const icao24 = rawIcao24.trim().toLowerCase();\n    const callsign = rawCallsign.trim().toUpperCase();\n    if (rawIcao24 && !/^[0-9a-f]{6}$/.test(icao24)) throw new ApiError(400, 'Expected a six-character hexadecimal ICAO address', '');\n    if (rawCallsign && !/^[A-Z0-9]{1,8}$/.test(callsign)) throw new ApiError(400, 'Expected an alphanumeric callsign of at most eight characters', '');\n    req = { ...req, icao24, callsign };\n    if (icao24 || callsign) await admitIdentifierLookup(ctx.request);\n\n    const redistributableOnly = requiresRedistributableProviders(ctx.request);\n    const cacheKey = `${buildCacheKey(req)}${redistributableOnly ? ':redistributable' : ''}`;\n\n    let result: { positions: PositionSample[]; source: string } | null = null;\n    try {\n        const positiveTtl = req.callsign ? CALLSIGN_CACHE_TTL : CACHE_TTL;\n        const negativeTtl = req.callsign ? CALLSIGN_NEGATIVE_TTL : CACHE_TTL;\n        result = await cachedFetchJson<{ positions: PositionSample[]; source: string }>(\n            cacheKey, positiveTtl, async () => {\n                const relayBase = getRelayBaseUrl();\n                const isCallsignOnly = !!req.callsign && !req.icao24 && isDegenerateBbox(req);\n\n                // For callsign-only searches, try Wingbits first — commercial flights like UAE20\n                // are Wingbits-exclusive and not visible in OpenSky. Trying OpenSky first wastes\n                // time and may return an early hit with no callsign match.","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/server/worldmonitor/aviation/v1/track-aircraft.ts#L104-L140","documentation":"When a callsign is provided to trackAircraft, it must match /^[A-Z0-9]{1,8}$/ after trimming and uppercasing — 1 to 8 alphanumeric characters. Anything with symbols, spaces, or more than 8 characters throws ApiError(400, 'Expected an alphanumeric callsign of at most eight characters').","triggerScenarios":"Calling track-aircraft with callsign 'UAL1234 ', 'DLH-441', 'SPEEDBIRD9' (9 chars), or any value containing dots/dashes/slashes.","commonSituations":"Radio-style spoken callsigns ('Speedbird two six six') pasted verbatim; airline-prefixed strings with hyphens from external systems; duplicate suffixes from concatenated logs.","solutions":["Strip non-alphanumerics and uppercase, then cap at 8 characters before calling","Use the ICAO-style callsign (e.g. 'BAW266') not the airline name or radio callsign","If unsure, pass the icao24 instead and omit callsign"],"exampleFix":"// before\nawait trackAircraft(ctx, { callsign: 'DLH-441' });\n// after\nconst callsign = raw.replace(/[^A-Z0-9]/gi, '').toUpperCase().slice(0, 8);\nawait trackAircraft(ctx, { callsign });","handlingStrategy":"validation","validationCode":"if (callsign && !/^[A-Z0-9]{1,8}$/.test(callsign.trim().toUpperCase())) throw new Error('callsign must be 1-8 alphanumerics');","typeGuard":"const isCallsign = (v: unknown): v is string => typeof v === 'string' && /^[A-Z0-9]{1,8}$/.test(v.trim().toUpperCase());","tryCatchPattern":"try {\n  return await trackAircraft(ctx, { callsign });\n} catch (e) {\n  if (e instanceof ApiError && e.status === 400) {\n    return { error: e.message, hint: 'use ICAO callsign like BAW266, max 8 alphanumerics' };\n  }\n  throw e;\n}","preventionTips":["Normalize callsigns: strip symbols, uppercase, cap at 8 chars","Use ICAO telephony designators, not marketing names","Prefer icao24 lookups when callsign format is uncertain"],"tags":["validation","format","aviation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}