{"record":{"id":"0d6b6ca744a208e5","repo":"hasura/graphql-engine","slug":"marshal-file-w","errorCode":null,"errorMessage":"marshal file: %w","messagePattern":"marshal file: %w","errorType":"exception","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"cli/global_config.go","lineNumber":100,"sourceCode":"\tif c.ShowUpdateNotification == nil {\n\t\ttrueVal := true\n\t\tc.ShowUpdateNotification = &trueVal\n\t\tc.shoudlWrite = true\n\t}\n\n\tif c.CLIEnvironment == \"\" {\n\t\tc.CLIEnvironment = DefaultEnvironment\n\t}\n\n\treturn nil\n}\n\nfunc (c *rawGlobalConfig) write(filename string) error {\n\tvar op errors.Op = \"cli.rawGlobalConfig.write\"\n\n\tb, err := json.MarshalIndent(c, \"\", \"  \")\n\tif err != nil {\n\t\treturn errors.E(op, fmt.Errorf(\"marshal file: %w\", err))\n\t}\n\n\terr = os.WriteFile(filename, b, 0o644)\n\tif err != nil {\n\t\treturn errors.E(op, fmt.Errorf(\"write file: %w\", err))\n\t}\n\n\treturn nil\n}\n\n// setupGlobConfig ensures that global config directory and file exists and\n// reads it into the GlobalConfig object.\nfunc (ec *ExecutionContext) setupGlobalConfig() error {\n\tvar op errors.Op = \"cli.ExecutionContext.setupGlobalConfig\"\n\t// check if the directory name is set, else default\n\tif len(ec.GlobalConfigDir) == 0 {\n\t\tec.Logger.Debug(\"global config directory is not pre-set, defaulting\")\n","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/global_config.go#L82-L118","documentation":"rawGlobalConfig.write serializes the in-memory global config with json.MarshalIndent before saving; this error wraps a marshaling failure. Because the struct holds plain JSON-compatible values, it essentially only fires when a field contains data JSON cannot represent (NaN/Inf floats, cycles, or unsupported channel/func types after struct changes).","triggerScenarios":"setupGlobalConfig persisting a rawGlobalConfig containing a NaN or +Inf float (e.g. parsed from an exotic config source) or a struct layout with unmarshalable fields introduced by a version change.","commonSituations":"Version upgrade adding a field the old writer cannot marshal; programmatic manipulation of the config struct injecting NaN; extremely rare in normal CLI usage.","solutions":["Inspect and sanitize config values (replace NaN/Inf with valid numbers or omit the key) before saving","Regenerate the global config from defaults (delete it and re-run init/setup)","Pin/align tool versions between write and read paths if a schema change is suspected"],"exampleFix":"// before\nraw.Timeout = math.NaN()   // json: unsupported value: NaN\n// after\nraw.Timeout = 30 * time.Second","handlingStrategy":"try-catch","validationCode":"if _, err := json.MarshalIndent(rawCfg, \"\", \"  \"); err != nil {\n    log.Fatalf(\"global config contains unserializable values: %v\", err)\n}","typeGuard":"func isMarshalable(v any) bool {\n    _, err := json.Marshal(v)\n    return err == nil\n}","tryCatchPattern":"if err := setupGlobalConfig(); err != nil {\n    var typeErr *json.UnsupportedTypeError\n    if stderrors.As(err, &typeErr) {\n        // a struct field holds an unmarshalable value; sanitize or drop it before retrying\n    }\n}","preventionTips":["Sanitize float fields (reject NaN/Inf) before saving","Keep tool versions consistent between read and write paths","Regenerate from defaults when the config becomes unmarshalable"],"tags":["config","json","marshal-error","go"],"backgroundTag":"json-serialization-failure","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}