{"record":{"id":"cb1fb3c99c189d3c","repo":"ramensoftware/windhawk","slug":"invalid-object-array-schema-definition","errorCode":null,"errorMessage":"Invalid object array schema definition.","messagePattern":"Invalid object array schema definition\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/windhawk-frontend/apps/windhawk-frontend/src/app/panel/mod-details/tabs/settings/core/yamlConverter.ts","lineNumber":189,"sourceCode":"\n  if (typeof value === 'number') {\n    return { kind: SettingType.Number, value, defaultValue: 0 };\n  }\n\n  if (typeof value === 'string') {\n    return { kind: SettingType.String, value, defaultValue: '' };\n  }\n\n  if (!Array.isArray(value) || value.length === 0) {\n    throw new Error('Initial settings arrays must contain at least one template entry.');\n  }\n\n  const arrayValue: unknown[] = value;\n\n  if (isInitialSettingsCollection(arrayValue)) {\n    const [first] = arrayValue;\n    if (first.length === 0) {\n      throw new Error('Invalid object array schema definition.');\n    }\n    return { kind: SettingType.ObjectArray, value: arrayValue, children: first };\n  }\n\n  if (isInitialSettingsArray(arrayValue)) {\n    return { kind: SettingType.NestedObject, value: arrayValue, children: arrayValue };\n  }\n\n  if (isNumberArrayValue(arrayValue)) {\n    return { kind: SettingType.NumberArray, value: arrayValue, defaultValue: 0 };\n  }\n\n  if (isStringArrayValue(arrayValue)) {\n    return { kind: SettingType.StringArray, value: arrayValue, defaultValue: '' };\n  }\n\n  throw new Error(`Unknown setting type for value: ${JSON.stringify(value)}`);\n}","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/ramensoftware/windhawk/blob/61d99ed8e182e1af1b60109612b6763ad1b4b74e/src/windhawk-frontend/apps/windhawk-frontend/src/app/panel/mod-details/tabs/settings/core/yamlConverter.ts#L171-L207","documentation":"describeSetting() detects an object-array schema via isInitialSettingsCollection, which inspects the first element as the row template. If that first entry is an empty array (zero columns/fields), there is no template to derive ObjectArray children from, so the converter throws.","triggerScenarios":"Passing an array of arrays whose first element is `[]`, e.g. `[[ ]]`, to describeSetting through descriptor/schemaDescriptor/dataDescriptor when parsing an object-array settings definition.","commonSituations":"A mod's settings table is declared but all column definitions were removed; an export tool serializes an empty header row.","solutions":["Ensure the first array entry defines at least one field/column for the object rows","Remove the empty object-array definition entirely if the table is unused","Check that isInitialSettingsCollection's contract (first element = template) is satisfied by your data"],"exampleFix":"// before\ndescribeSetting([[]])\n// after\ndescribeSetting([[{ id: 'name', type: 'string' }]])","handlingStrategy":"type-guard","validationCode":"const isObjectArraySchema = (v: unknown): boolean =>\n  Array.isArray(v) && Array.isArray(v[0]) && (v[0] as unknown[]).length > 0;\nif (!isObjectArraySchema(raw)) throw new Error('object array needs a non-empty template row');","typeGuard":"const hasTemplateRow = (v: unknown[]): v is [unknown[], ...unknown[][]] =>\n  Array.isArray(v[0]) && v[0].length > 0;","tryCatchPattern":"try { desc = describeSetting(value); } catch (e) { if (e.message.includes('Invalid object array schema')) return null; throw e; }","preventionTips":["Ensure the first element of any object-array definition lists at least one column","Lint mod settings blocks for empty header rows","Document the first-entry-as-template contract for isInitialSettingsCollection consumers"],"tags":["yaml","schema","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"61d99ed8e182e1af1b60109612b6763ad1b4b74e","analyzedAt":"2026-09-12T14:02:41.115Z","contentChangedAt":"2026-09-12T14:02:41.115Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}