bytebase/bytebase · warning

cannot access user and system tables at the same time

Error message

cannot access user and system tables at the same time

What it means

MixUserSystemTablesError is a sentinel error declared in base/span.go: a query span analysis found a statement that mixes references to user tables and system tables (e.g. joining a business table with information_schema or pg_catalog views). Query span extractors refuse to classify such mixed-access queries because lineage/source-column attribution across user and system catalogs is not meaningful.

Source

Thrown at backend/plugin/parser/base/span.go:34

type QueryType int

const (
	// Type can not be recognized for now.
	QueryTypeUnknown QueryType = iota
	// The read-only select query.
	Select
	// The explain query.
	Explain
	// The read-only select query for reading information schema and system objects.
	SelectInfoSchema
	// The DDL query that changes schema.
	DDL
	// The DML query that changes table data.
	DML
)

var (
	MixUserSystemTablesError = errors.Errorf("cannot access user and system tables at the same time")
)

type SourceColumnSet map[ColumnResource]bool

// MergeSourceColumnSet merges two source column maps, returns true if there is difference.
func MergeSourceColumnSet(m, n SourceColumnSet) (SourceColumnSet, bool) {
	r := make(SourceColumnSet)
	for k := range m {
		r[k] = true
	}
	for k := range n {
		if _, ok := r[k]; !ok {
			r[k] = true
		}
	}

	return r, len(r) != len(m)
}

View on GitHub (pinned to 1870550677)

Solutions

  1. Split the query: run the user-table part and the system-catalog part as separate statements.
  2. Remove or replace system-table references (e.g. hardcode metadata or fetch it via a separate query) so the statement touches only user tables.
  3. Catch this sentinel (errors.Is(err, base.MixUserSystemTablesError)) and skip query-span/lineage features for such statements instead of failing.

Example fix

// before
rows, err := db.Query("SELECT u.name, t.table_name FROM users u JOIN information_schema.tables t ON t.table_schema = u.db")
// after
rows, err := db.Query("SELECT u.name FROM users u") // fetch catalog info in a separate query
metaRows, _ := db.Query("SELECT table_name FROM information_schema.tables WHERE table_schema = $1", dbName)
Defensive patterns

Strategy: try-catch

Validate before calling

// heuristic pre-check: reject queries referencing both user tables and catalog schemas
if mentionsSystemSchema(sql) && mentionsUserTables(sql) {
	return errors.New("query mixes user and system tables; split it")
}

Type guard

func isMixedTableError(err error) bool {
	return errors.Is(err, base.MixUserSystemTablesError)
}

Try / catch

span, err := extractor.GetQuerySpan(ctx, q)
if errors.Is(err, base.MixUserSystemTablesError) {
	// skip lineage for mixed queries; not a hard failure
	return nil, nil
}

Prevention

When it happens

Trigger: getQuerySpan/GetQuerySpan/getOmniQuerySpan (e.g. Doris and GoogleSQL extractors) run isMixedQuery/classifyAccess over the statement's accessed tables and detect both system and user tables in one query; the sentinel is returned as the query span error. Triggering SQL example: SELECT * FROM my_table, information_schema.tables WHERE ...

Common situations: Ad-hoc queries in the SQL editor joining catalog/metadata views with application tables; data-export statements mixing pg_catalog or information_schema with user tables; queries written against administrative dashboards.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/779ece07255e1364. Report an issue: GitHub.