{"record":{"id":"3154cfd8b3c29ac6","repo":"can1357/oh-my-pi","slug":"this-cannot-be-used-as-a-root-definition","errorCode":null,"errorMessage":"\"this\" cannot be used as a root definition","messagePattern":"\"this\" cannot be used as a root definition","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/type.ts","lineNumber":2583,"sourceCode":"\tresolve.hasGeneric = outer?.hasGeneric;\n\tresolve.generic = outer?.generic;\n\treturn resolve;\n}\n\nfunction parseGenericArgument(definition: unknown, outer?: AliasResolver): IR {\n\tif (outer === undefined) {\n\t\ttry {\n\t\t\treturn parseDef(definition);\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof OmpTypeError) || !error.message.includes('unknown keyword \"this\"')) throw error;\n\t\t}\n\t}\n\tlet root: IR | undefined;\n\tconst self: IR = {\n\t\tk: \"alias\",\n\t\tname: \"this\",\n\t\tresolve: () => {\n\t\t\tif (root === undefined || root === self) throw new OmpTypeError('\"this\" cannot be used as a root definition');\n\t\t\treturn root;\n\t\t},\n\t};\n\tconst resolve = ((name: string) => (name === \"this\" ? self : outer?.(name))) as AliasResolver;\n\tif (outer !== undefined) {\n\t\tresolve.hasGeneric = outer.hasGeneric;\n\t\tresolve.generic = outer.generic;\n\t} else {\n\t\t// The retry only exists to serve \"this\"; parses of this-free member\n\t\t// strings inside the definition may still share the string cache.\n\t\tmarkThisOnlyResolver(resolve);\n\t}\n\troot = parseDef(definition, resolve);\n\tif (root === self) throw new OmpTypeError('\"this\" cannot be used as a root definition');\n\treturn root;\n}\n\nfunction genericBodyIR(","sourceCodeStart":2565,"sourceCodeEnd":2601,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/type.ts#L2565-L2601","documentation":"Inside a definition, the self-reference 'this' resolves via an alias IR whose resolve() throws when the root definition is not yet available or when the alias resolves to itself. Using 'this' as the entire root definition means resolution is circular with no base case, so the library throws OmpTypeError.","triggerScenarios":"Parsing the definition 'this' itself (root === self), or referencing 'this' before root is assigned such that resolve() runs while root is undefined.","commonSituations":"Writing a recursive schema whose whole body is just 'this'; an editing slip where the actual structure was deleted leaving only the self-reference; generated code emitting a bare self-reference.","solutions":["Give the root a concrete shape and use 'this' only nested inside it, e.g. type({ \"next?\": 'this' })","Never use 'this' as the top-level definition string","If a truly self-recursive value type is needed, structure it via properties/arrays that wrap 'this'"],"exampleFix":"// before\nconst T = type('this'); // throws\n// after\nconst T = type({ value: 'number', next: 'this?' });","handlingStrategy":"validation","validationCode":"function assertNotBareThis(def: unknown) {\n  if (typeof def === 'string' && def.trim() === 'this') {\n    throw new Error('root definition cannot be bare \"this\"; wrap it in a structure');\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const T = type(def);\n} catch (err) {\n  if (err instanceof OmpTypeError && err.message.includes('\"this\" cannot be used as a root definition')) {\n    throw new Error(`Make \"${String(def)}\" a structure that nests \"this\" (e.g. { next: 'this?' })`);\n  }\n  throw err;\n}","preventionTips":["Use 'this' only in nested positions (properties, array elements)","For recursion, prefer named aliases with a concrete base case","Lint definition strings for a lone 'this' body"],"tags":["recursion","self-reference","schema","omptype"],"backgroundTag":"circular-self-reference","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}