{"record":{"id":"f5b3f3c4406ca88c","repo":"plandex-ai/plandex","slug":"error-hashing-models-v","errorCode":null,"errorMessage":"error hashing models: %v","messagePattern":"error hashing models: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/custom_models.go","lineNumber":126,"sourceCode":"\t}\n\n\tvar localClientModelsInput shared.ClientModelsInput\n\terr = json.Unmarshal(localJsonData, &localClientModelsInput)\n\tif err != nil {\n\t\treturn CustomModelsCheckLocalChangesResult{}, fmt.Errorf(\"error unmarshalling JSON file: %v\", err)\n\t}\n\n\tlocalModelsInput := localClientModelsInput.ToModelsInput()\n\n\tlastSavedHash, err := os.ReadFile(hashPath)\n\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn CustomModelsCheckLocalChangesResult{}, fmt.Errorf(\"error reading hash file: %v\", err)\n\t}\n\n\tcurrentHash, err := localModelsInput.Hash()\n\tif err != nil {\n\t\treturn CustomModelsCheckLocalChangesResult{}, fmt.Errorf(\"error hashing models: %v\", err)\n\t}\n\n\treturn CustomModelsCheckLocalChangesResult{\n\t\tHasLocalChanges:  currentHash != string(lastSavedHash),\n\t\tLocalModelsInput: localModelsInput,\n\t}, nil\n}\n\nfunc WriteCustomModelsFile(path string, modelsInput *shared.ModelsInput) error {\n\terr := os.MkdirAll(filepath.Dir(path), 0755)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating directory: %v\", err)\n\t}\n\n\tclientModelsInput := modelsInput.ToClientModelsInput()\n\tclientModelsInput.PrepareUpdate()\n\n\tjsonData, err := json.MarshalIndent(clientModelsInput, \"\", \"  \")","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/custom_models.go#L108-L144","documentation":"CustomModelsCheckLocalChanges computes a hash of the local ModelsInput via localModelsInput.Hash(); a hashing failure is wrapped as 'error hashing models: %v'. Hashing depends on serializing the model input, so this indicates the in-memory data cannot be canonicalized.","triggerScenarios":"localModelsInput.Hash() returns an error — e.g. the serialization step inside Hash fails because some model/provider entry in the local input cannot be marshalled deterministically (nil/invalid nested data).","commonSituations":"Corrupt or partially parsed entries from a malformed local JSON (feeding into the input); custom model definitions with unsupported field values; a bug/edge case in the Hash implementation for unusual model shapes.","solutions":["Check the wrapped hash error for the failing serialization reason","Fix or remove the offending custom model/provider entries in the local JSON","Delete local custom-models state and resync from the server to rebuild a clean input","If reproducible with valid data, report/inspect the Hash implementation for the unsupported case"],"exampleFix":"// before\ncurrentHash, err := localModelsInput.Hash()\nif err != nil {\n    return CustomModelsCheckLocalChangesResult{}, fmt.Errorf(\"error hashing models: %v\", err)\n}\n// after: caller resyncs on hash failure\nif _, err := localModelsInput.Hash(); err != nil {\n    return SyncCustomModels() // rebuild local state from server\n}","handlingStrategy":"fallback","validationCode":"if len(input.CustomModels) == 0 && len(input.CustomProviders) == 0 {\n    return // nothing to hash; skip comparison\n}","typeGuard":null,"tryCatchPattern":"res, err := CustomModelsCheckLocalChanges(...)\nif err != nil && strings.Contains(err.Error(), \"error hashing models\") {\n    // local input is unusable — rebuild it from the server\n    return SyncCustomModels()\n}","preventionTips":["Ensure custom model entries are fully populated before writing local state","Resync from the server whenever local JSON failed to parse","Report reproducible hash failures on valid data as library bugs"],"tags":["hashing","custom-models","serialization","cli"],"backgroundTag":"hash-computation-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}