{"record":{"id":"7f579ea8c84962de","repo":"cayleygraph/cayley","slug":"could-not-retrieve-connmaxlifetime-from-options","errorCode":null,"errorMessage":"could not retrieve connmaxlifetime from options: %v","messagePattern":"could not retrieve connmaxlifetime from options: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graph/sql/quadstore.go","lineNumber":134,"sourceCode":"}\n\nfunc connect(addr string, flavor string, opts graph.Options) (*sql.DB, error) {\n\tmaxOpenConnections, err := opts.IntKey(\"maxopenconnections\", -1)\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not retrieve maxopenconnections from options: %v\", err)\n\t}\n\n\tmaxIdleConnections, err := opts.IntKey(\"maxidleconnections\", -1)\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not retrieve maxIdleConnections from options: %v\", err)\n\t}\n\n\tconnMaxLifetime, err := opts.StringKey(\"connmaxlifetime\", \"\")\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not retrieve connmaxlifetime from options: %v\", err)\n\t}\n\n\tvar connDuration time.Duration\n\tif connMaxLifetime != \"\" {\n\t\tconnDuration, err = time.ParseDuration(connMaxLifetime)\n\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"couldn't parse connmaxlifetime string: %v\", err)\n\t\t}\n\t}\n\n\t// TODO(barakmich): Parse options for more friendly addr\n\tconn, err := sql.Open(flavor, addr)\n\tif err != nil {\n\t\tclog.Errorf(\"Couldn't open database at %s: %#v\", addr, err)\n\t\treturn nil, err\n\t}\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/sql/quadstore.go#L116-L152","documentation":"connect reads the \"connmaxlifetime\" string option via graph.Options.StringKey (default \"\"). If StringKey returns an error — e.g. the key is present but not a string — connect wraps it as \"could not retrieve connmaxlifetime from options\". Reached through Init or New.","triggerScenarios":"New/Init call where opts has \"connmaxlifetime\" set to a non-string value (int, bool, map).","commonSituations":"Config where connmaxlifetime is an unquoted number (e.g. 3600 instead of \"1h\"); typed Options builders passing a duration object instead of a string.","solutions":["Set \"connmaxlifetime\" as a string duration (e.g. \"1h30m\") or omit the key.","Quote the value in config files so loaders deliver a string.","Check the wrapped underlying error for the exact type failure."],"exampleFix":"// before\n{\"connmaxlifetime\": 3600}\n// after\n{\"connmaxlifetime\": \"1h\"}","handlingStrategy":"validation","validationCode":"if v, ok := opts[\"connmaxlifetime\"]; ok {\n    if _, isStr := v.(string); !isStr {\n        return fmt.Errorf(\"connmaxlifetime must be a string duration, got %T\", v)\n    }\n}","typeGuard":null,"tryCatchPattern":"qs, err := quadstore.New(addr, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"connmaxlifetime\") && strings.Contains(err.Error(), \"could not retrieve\") {\n        // make the value a string duration\n    }\n}","preventionTips":["Quote connmaxlifetime values (\"1h\") so loaders deliver strings.","Never pass numbers or duration objects as the raw option value.","Validate the options map types before New/Init."],"tags":["sql","options","config"],"backgroundTag":"invalid-config-value","analyzedSha":"81dcd7d73e45136bc0d01802a8ba4685d8a533eb","analyzedAt":"2026-09-06T06:14:12.358Z","contentChangedAt":"2026-09-06T06:14:12.358Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}