temporalio/temporal · error

error building DSN: %w

Error message

error building DSN: %w

What it means

Wrapped in createDBConnection when buildDSN fails while constructing the SQLite data source name. buildDSN derives the DSN from the SQL config (database file path and ConnectAttributes), so this indicates invalid or missing SQLite configuration. The wrapped error from buildDSN states the exact reason.

Source

Thrown at common/persistence/sql/sqlplugin/sqlite/plugin.go:84

		return nil, err
	}
	db := newDB(dbKind, cfg.DatabaseName, conn, nil, logger)
	db.OnClose(func() { p.connPool.Close(cfg) }) // remove reference
	return db, nil
}

// createDBConnection creates a returns a reference to a logical connection to the
// underlying SQL database. The returned object is tied to a single
// SQL database and the object can be used to perform CRUD operations on
// the tables in the database.
func (p *plugin) createDBConnection(
	cfg *config.SQL,
	_ resolver.ServiceResolver,
	logger log.Logger,
) (*sqlx.DB, error) {
	dsn, err := buildDSN(cfg)
	if err != nil {
		return nil, fmt.Errorf("error building DSN: %w", err)
	}

	db, err := sqlx.Connect(goSQLDriverName, dsn)
	if err != nil {
		return nil, err
	}

	// Connection pool settings.
	//
	// By default, SQLite only supports a single writer at a time (see
	// https://github.com/mattn/go-sqlite3#faq). Without WAL (Write-Ahead Logging)
	// mode, concurrent connections will encounter "database is locked" errors.
	// With WAL mode enabled (journal_mode=wal), SQLite supports concurrent readers
	// alongside a single writer, making multiple connections safe and beneficial
	// for throughput.
	//
	// These settings mirror the behavior of the MySQL and PostgreSQL plugins:
	// respect the user's config values when set, otherwise default to 1 for

View on GitHub (pinned to bde624efd1)

Solutions

  1. Fix cfg.ConnectAttributes entries to be valid key=value pairs.
  2. Confirm the database name/path in the SQL config is set and writable for the sqlite file.
  3. Compare your config against a known-good sqlite example in config/.
  4. Check the inner buildDSN error for the specific parse failure.

Example fix

// before
connectAttributes: {"cache": "shared", "mode": "ro" "bad"}
// after
connectAttributes: {"cache": "shared", "mode": "ro"}
Defensive patterns

Strategy: validation

Validate before calling

// Go: pre-validate sqlite connect attributes
for _, attr := range cfg.ConnectAttributes {
    if len(strings.Split(attr, "=")) < 2 {
        return fmt.Errorf("invalid sqlite connect attribute %q: expected key=value", attr)
    }
}

Try / catch

// Go
if err != nil && strings.Contains(err.Error(), "error building DSN") {
    return fmt.Errorf("check sqlite config (ConnectAttributes, database path): %w", err)
}

Prevention

When it happens

Trigger: Starting the persistence layer with sqlite driver when cfg.ConnectAttributes contains malformed URI parameters (e.g. 'x=y=z' or unparseable key=value pairs) or the config otherwise prevents DSN construction.

Common situations: Misconfigured sqlite ConnectAttributes in the Temporal config YAML; typos like missing '=' in connection attributes; using sqlite in environments where config was copied from mysql/postgres setups.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/7fde2f169c2258ab. Report an issue: GitHub.