{"record":{"id":"27986469c0605eef","repo":"lyswhut/lx-music-desktop","slug":"type-size-type-no-match","errorCode":null,"errorMessage":"${type} size type no match","messagePattern":"(.+?) size type no match","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/core/useApp/useDeeplink/utils.js","lineNumber":24,"sourceCode":"  const errorDialog = message => {\n    dialog({\n      message: `${t('deep_link__handle_error_tip', { message })}`,\n      confirmButtonText: t('ok'),\n    })\n  }\n\n  return errorDialog\n}\n\nexport const sources = ['kw', 'kg', 'tx', 'wy', 'mg']\nexport const sourceVerify = source => {\n  if (!sources.includes(source)) throw new Error('Source no match')\n}\n\nexport const qualitys = ['128k', '320k', 'flac', 'flac24bit']\nexport const qualityFilter = (source, types) => {\n  types = types.filter(({ type }) => qualitys.includes(type)).map(({ type, size, hash }) => {\n    if (size != null && typeof size != 'string') throw new Error(type + ' size type no match')\n    if (source == 'kg' && typeof hash != 'string') throw new Error(type + ' hash type no match')\n    return hash == null ? { type, size } : { type, size, hash }\n  })\n  if (!types.length) throw new Error('quality no match')\n  return types\n}\n\nexport const dataVerify = (rules, data) => {\n  const newData = {}\n  for (const rule of rules) {\n    const val = data[rule.key]\n    if (rule.required && val == null) throw new Error(rule.key + ' missing')\n    if (val != null) {\n      if (rule.types && !rule.types.includes(typeof val)) throw new Error(rule.key + ' type no match')\n      if (rule.max && String(val).length > rule.max) throw new Error(rule.key + ' max length no match')\n      if (rule.min && String(val).length > rule.min) throw new Error(rule.key + ' min length no match')\n    }\n    newData[rule.key] = val","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/lyswhut/lx-music-desktop/blob/9c364b482e5621a1d38b50e8610d2fb974457e6e/src/renderer/core/useApp/useDeeplink/utils.js#L6-L42","documentation":"Inside qualityFilter (utils.js:24). For each quality entry, an optional `size` field must be a string (e.g. '4.2'). If `size` is present and its typeof is not 'string', the entry's `type` is interpolated into the message ('<type> size type no match') and the whole play-music call aborts before types are returned.","triggerScenarios":"A play-music deep link whose musicInfo.types array contains an entry like {type:'320k', size:4.2} (number) or {type:'flac', size:{...}} instead of size:'4.2'. qualityFilter is called from useMusicAction.js:136 after the source switch.","commonSituations":"The sender serializes size as a JSON number rather than a string; schema drift between sender and receiver; a manually constructed link with the wrong primitive.","solutions":["Have the sender emit `size` as a string consistently.","Normalize entries before qualityFilter: coerce non-null size with String(size).","Broaden the check to accept numbers and convert them, if both shapes are legitimate.","Reject the offending entry and continue rather than failing the entire list."],"exampleFix":"// before\n    if (size != null && typeof size != 'string') throw new Error(type + ' size type no match')\n\n// after - coerce instead of throw, preserving the string contract\n    if (size != null && typeof size != 'string') size = String(size)","handlingStrategy":"validation","validationCode":"const normalizeQualityTypes = (types) =>\n  types.map(t => (t.size != null && typeof t.size !== 'string') ? { ...t, size: String(t.size) } : t)\n// before qualityFilter:\nmusicInfo.types = normalizeQualityTypes(musicInfo.types)","typeGuard":"const isQualityEntry = (e) =>\n  e != null && typeof e === 'object' && typeof e.type === 'string' &&\n  (e.size == null || typeof e.size === 'string')","tryCatchPattern":"try {\n  musicInfo.types = qualityFilter(musicInfo.source, musicInfo.types)\n} catch (e) {\n  errorDialog(e.message)\n}","preventionTips":["Have the sender stringify `size` when building the link.","Normalize types entries (coerce size to string) before calling qualityFilter.","Validate each entry's shape at the boundary so a bad entry doesn't abort the whole list."],"tags":["deeplink","validation","quality","type-coercion"],"backgroundTag":null,"analyzedSha":"9c364b482e5621a1d38b50e8610d2fb974457e6e","analyzedAt":"2026-08-12T15:14:48.244Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}