github/github-mcp-server · error

failed to open log file: %w

Error message

failed to open log file: %w

What it means

RunHTTPServer failed to open cfg.LogFilePath with os.OpenFile(O_CREATE|O_WRONLY|O_APPEND, 0600) - the OS refused to create or append the log file, so structured logging cannot start and startup aborts.

Source

Thrown at pkg/http/server.go:117

	EnabledFeatures []string

	// InsidersMode expands to the curated set of feature flags enabled for insiders.
	InsidersMode bool
}

func RunHTTPServer(cfg ServerConfig) error {
	// Create app context
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer stop()

	t, dumpTranslations := translations.TranslationHelper()

	var slogHandler slog.Handler
	var logOutput io.Writer
	if cfg.LogFilePath != "" {
		file, err := os.OpenFile(cfg.LogFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
		if err != nil {
			return fmt.Errorf("failed to open log file: %w", err)
		}
		logOutput = file
		slogHandler = slog.NewTextHandler(logOutput, &slog.HandlerOptions{Level: slog.LevelDebug})
	} else {
		logOutput = os.Stderr
		slogHandler = slog.NewTextHandler(logOutput, &slog.HandlerOptions{Level: slog.LevelInfo})
	}
	logger := slog.New(slogHandler)
	logger.Info("starting server", "version", cfg.Version, "host", cfg.Host, "lockdownEnabled", cfg.LockdownMode, "readOnly", cfg.ReadOnly, "insidersMode", cfg.InsidersMode)

	apiHost, err := utils.NewAPIHost(cfg.Host)
	if err != nil {
		return fmt.Errorf("failed to parse API host: %w", err)
	}
	hostType, err := utils.ParseHostType(cfg.Host)
	if err != nil {
		return fmt.Errorf("failed to classify API host: %w", err)
	}

View on GitHub (pinned to 0ea1f775a7)

Solutions

  1. Create the parent directory and give the server user write access (mkdir -p && chown)
  2. Confirm the path is a file location, not a directory
  3. On read-only filesystems, omit LogFilePath so logs go to stderr, or mount a writable volume at that path

Example fix

# before
GITHUB_MCP_LOG_FILE=/var/log/mcp/server.log
# after
mkdir -p /var/log/mcp && chown appuser /var/log/mcp
GITHUB_MCP_LOG_FILE=/var/log/mcp/server.log
Defensive patterns

Strategy: validation

Validate before calling

if cfg.LogFilePath != "" {
	if dir := filepath.Dir(cfg.LogFilePath); dir != "" {
		if err := os.MkdirAll(dir, 0o750); err != nil {
			return fmt.Errorf("log dir not creatable: %w", err)
		}
	}
	f, err := os.OpenFile(cfg.LogFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
	if err != nil { return err }
	_ = f.Close()
}

Prevention

When it happens

Trigger: Parent directory does not exist; permission denied for the server user; path points at a directory; read-only filesystem (container image); disk full or SELinux/AppArmor denial.

Common situations: Containers mounting volumes at different paths than configured; running as non-root against a root-owned log dir; distroless/read-only root filesystems; Kubernetes emptyDir not mounted where expected.

Related errors


AI-assisted analysis of github/github-mcp-server@0ea1f775a7 (2026-08-15). Data as JSON: /api/errors/7064e059f094dff0. Report an issue: GitHub.