{"record":{"id":"007d55780268e7a3","repo":"t8y2/dbx","slug":"query-timed-out-after-ds","errorCode":null,"errorMessage":"query timed out after %ds","messagePattern":"query timed out after (.+?)s","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/oracle-go/main.go","lineNumber":5112,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\trows, queryErr = db.QueryContext(ctx, sqlText, args...)\n\t}\n\ts.activeCancelMu.Lock()\n\ts.activeCancel = nil\n\tif s.activeTimer != nil {\n\t\ts.activeTimer.Stop()\n\t\ts.activeTimer = nil\n\t}\n\ttimedOut := s.activeTimedOut\n\tif queryErr != nil {\n\t\tcancel()\n\t} else if timedOut {\n\t\tcancel()\n\t\tif rows != nil {\n\t\t\trows.Close()\n\t\t}\n\t\tqueryErr = fmt.Errorf(\"query timed out after %ds\", timeoutSecs)\n\t} else {\n\t\ts.activeRows[rows] = cancel\n\t}\n\ts.activeCancelMu.Unlock()\n\treturn rows, queryErr\n}\n\nfunc (s *server) cancelActiveQuery() {\n\ts.activeCancelMu.Lock()\n\tcancels := make([]context.CancelFunc, 0, len(s.activeRows)+1)\n\tif s.activeCancel != nil {\n\t\tcancels = append(cancels, s.activeCancel)\n\t}\n\tfor _, cancel := range s.activeRows {\n\t\tcancels = append(cancels, cancel)\n\t}\n\ts.activeCancelMu.Unlock()\n\tfor _, cancel := range cancels {","sourceCodeStart":5094,"sourceCodeEnd":5130,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/oracle-go/main.go#L5094-L5130","documentation":"The driver wraps statement execution with a context timeout; when the timeout elapses (timedOut branch) it cancels the context, closes any rows, and returns queryErr = fmt.Errorf(\"query timed out after %ds\", timeoutSecs) instead of rows. Callers such as listIndexes, the DDL helpers, and integration tests treat a nil queryErr as success and merge results.","triggerScenarios":"Any query executed through the timed-query helper (used by listIndexes, getTreeDialectDDL, getTableDialectDDL, TestKingbaseIntegration, and cassandra-go metadata.querySystemIndexes) taking longer than timeoutSecs — e.g. slow system-catalog queries on huge schemas or an unresponsive DB node.","commonSituations":"Introspecting a database with thousands of tables/indexes over a WAN, a Cassandra/Oracle node under load or doing GC pauses, network latency or packet loss, or a timeout value configured too low for large catalogs.","solutions":["Increase the query timeout (raise the timeoutSecs / context timeout passed to the driver).","Retry the specific metadata query — transient load often causes this; add backoff around listIndexes/DDL calls.","Narrow the metadata query scope (filter by schema/table instead of listing everything).","Check DB-side health: slow queries, GC pauses, network latency between client and server."],"exampleFix":"// before\nrows, err := s.queryWithTimeout(ctx, 5, query)\n// after\nrows, err := s.queryWithTimeout(ctx, 60, query) // larger budget for large catalogs","handlingStrategy":"retry","validationCode":"// no pre-call validation possible; ensure timeout budget is adequate for catalog size\nestTables := countTables(); timeout := max(30, estTables/100) // seconds","typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n\tindexes, err := drv.ListIndexes(schema, table)\n\tif err != nil && strings.Contains(err.Error(), \"query timed out\") {\n\t\ttime.Sleep(backoff(attempt)); continue\n\t}\n\treturn indexes, err\n}","preventionTips":["Size the timeout to the largest catalog you introspect, not the smallest.","Add bounded retry with backoff around metadata queries.","Scope queries to a specific schema instead of full-database listing.","Monitor DB-side latency/GC to distinguish load issues from config issues."],"tags":["timeout","network","query"],"backgroundTag":"query-timeout","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}