{"record":{"id":"7cbab61d9039da7a","repo":"wavetermdev/waveterm","slug":"atom-q-not-found","errorCode":null,"errorMessage":"atom %q not found","messagePattern":"atom %q not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tsunami/engine/rootelem.go","lineNumber":224,"sourceCode":"\nfunc (r *RootElem) GetAtomVal(name string) any {\n\tr.atomLock.Lock()\n\tdefer r.atomLock.Unlock()\n\n\tatom, ok := r.Atoms[name]\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn atom.GetVal()\n}\n\nfunc (r *RootElem) SetAtomVal(name string, val any) error {\n\tr.atomLock.Lock()\n\tdefer r.atomLock.Unlock()\n\n\tatom, ok := r.Atoms[name]\n\tif !ok {\n\t\treturn fmt.Errorf(\"atom %q not found\", name)\n\t}\n\treturn atom.SetVal(val)\n}\n\nfunc (r *RootElem) RemoveAtom(name string) {\n\tr.atomLock.Lock()\n\tdefer r.atomLock.Unlock()\n\n\tdelete(r.Atoms, name)\n}\n\nfunc validateCFunc(cfunc any) error {\n\tif cfunc == nil {\n\t\treturn fmt.Errorf(\"Component function cannot b nil\")\n\t}\n\trval := reflect.ValueOf(cfunc)\n\tif rval.Kind() != reflect.Func {\n\t\treturn fmt.Errorf(\"Component function must be a function\")","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/tsunami/engine/rootelem.go#L206-L242","documentation":"SetAtomVal looks up the named atom in the RootElem's Atoms map under atomLock and updates its value. If no atom with that name exists, it returns \"atom %q not found\". Atoms only exist if they were previously created/registered on this RootElem; they can also be removed via RemoveAtom. GetAtomVal silently returns nil for missing atoms, so this error only surfaces on writes.","triggerScenarios":"SetAtomVal(\"myAtom\", v) where \"myAtom\" was never created on the RootElem, was created on a different RootElem instance, or was deleted by RemoveAtom before the SetAtomVal call.","commonSituations":"Typo in the atom name; atom creation path not yet executed when an event handler writes it (initialization-order bug); atom removed on component unmount while an async callback still writes it.","solutions":["Verify the atom name matches the one created on this RootElem (check for typos)","Ensure the atom-creating code runs before any SetAtomVal call (initialization order)","Guard against RemoveAtom racing with async writes — remove the write when the atom is torn down","Check you are holding the same RootElem instance the atom was registered on"],"exampleFix":"// before\nerr := root.SetAtomVal(\"curentPath\", path) // typo + possibly never created\n// after\nif root.GetAtomVal(\"currentPath\") == nil {\n    root.CreateAtom(\"currentPath\", \"\") // ensure atom exists first\n}\nerr := root.SetAtomVal(\"currentPath\", path)","handlingStrategy":"validation","validationCode":"if root.GetAtomVal(\"currentPath\") == nil {\n    return fmt.Errorf(\"atom %q does not exist; create it before setting\", \"currentPath\")\n}","typeGuard":"func atomExists(r *engine.RootElem, name string) bool { return r.GetAtomVal(name) != nil }","tryCatchPattern":"if err := root.SetAtomVal(\"currentPath\", path); err != nil {\n    return fmt.Errorf(\"set atom failed: %w\", err) // includes the missing atom name\n}","preventionTips":["Centralize atom names as constants to avoid typos","Create atoms during component initialization, before any handlers can fire","Audit RemoveAtom call sites for async writers that may outlive the atom","Remember GetAtomVal returns nil silently for missing atoms — only writes surface the error"],"tags":["go","atoms","state","key-not-found"],"backgroundTag":"atom-not-found","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}