bytebase/bytebase · error

uid %d or gid %d exceeds maximum safe value

Error message

uid %d or gid %d exceeds maximum safe value

What it means

When the app runs as root, it re-executes initdb/start as the `bytebase` user via syscall.Credential, which carries uid/gid as uint32 but the kernel expects values within a range the code guards as <= math.MaxInt32. If the looked-up bytebase user's uid or gid exceeds MaxInt32, initDB returns this error before chowning anything. It is a defensive guard: such uid/gid values would overflow the signed int conversion used for os.Chown/Credential.

Source

Thrown at backend/resources/postgres/postgres.go:118

		if !os.IsNotExist(err) {
			return errors.Wrapf(err, "failed to check data directory path existence %q", path)
		}
		dirListToChown = append(dirListToChown, path)
		path = filepath.Dir(path)
	}
	slog.Debug("Data directory list to Chown", slog.Any("dirListToChown", dirListToChown))

	if err := os.MkdirAll(pgDataDir, 0700); err != nil {
		return errors.Wrapf(err, "failed to make postgres data directory %q", pgDataDir)
	}

	uid, gid, sameUser, err := shouldSwitchUser()
	if err != nil {
		return err
	}
	if !sameUser {
		if uid > math.MaxInt32 || gid > math.MaxInt32 {
			return errors.Errorf("uid %d or gid %d exceeds maximum safe value", uid, gid)
		}
		slog.Info(fmt.Sprintf("Recursively change owner of data directory %q to bytebase...", pgDataDir))
		for _, dir := range dirListToChown {
			slog.Info(fmt.Sprintf("Change owner of %q to bytebase", dir))
			if err := os.Chown(dir, int(uid), int(gid)); err != nil {
				return errors.Wrapf(err, "failed to change owner of %q to bytebase", dir)
			}
		}
	}

	args := []string{
		"-U", pgUser,
		"-D", pgDataDir,
	}
	p := exec.Command("initdb", args...)
	p.Env = append(os.Environ(),
		"LC_ALL=en_US.UTF-8",
		"LC_CTYPE=en_US.UTF-8",

View on GitHub (pinned to 1870550677)

Solutions

  1. Create the bytebase user with a small system uid: addgroup --gid 113 --system bytebase && adduser --uid 113 --system bytebase.
  2. Inspect the existing user's ids (id bytebase) and change them if they exceed 2147483647 (usermod -u / groupmod -g).
  3. Alternatively run Bytebase directly as a non-root user with a normal uid so the switch-user path is skipped entirely.

Example fix

// before
// adduser with a huge uid, then running bytebase as root
// after
// addgroup --gid 113 --system bytebase && adduser --uid 113 --system bytebase && adduser bytebase bytebase
Defensive patterns

Strategy: validation

Validate before calling

u, err := user.Lookup("bytebase")
if err != nil { return err }
uid, _ := strconv.ParseUint(u.Uid, 10, 64)
gid, _ := strconv.ParseUint(u.Gid, 10, 64)
if uid > math.MaxInt32 || gid > math.MaxInt32 {
    return fmt.Errorf("bytebase user uid/gid (%d/%d) too large; recreate with a system uid", uid, gid)
}

Try / catch

if err := postgres.StartEmbeddedInstance(ctx, cfg); err != nil && strings.Contains(err.Error(), "exceeds maximum safe value") {
    return fmt.Errorf("recreate the bytebase user with uid/gid <= %d (e.g. 113)", math.MaxInt32)
}

Prevention

When it happens

Trigger: Running Bytebase as root while the system's `bytebase` user (or whatever user.Lookup resolves) has a uid or gid greater than 2147483647 — possible on systems with large uid ranges (e.g. some LDAP/FreeIPA or user-namespace setups assigning high ids).

Common situations: Container/Kubernetes images with arbitrary high uid mappings, AD/LDAP-integrated hosts issuing uidNumbers beyond 2^31, misconfigured adduser creating an out-of-range uid.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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