Skip to content

Global flags marked as Local are still recognized after a subcommand #2208

@folliehiyuki

Description

@folliehiyuki

My urfave/cli version is

cli/v3 v3.4.1

Checklist

  • Are you running the latest v3 release? The list of releases is here.
  • Did you check the manual for your release? The v3 manual is here
  • Did you perform a search about this problem? Here's the GitHub guide about searching.

Dependency Management

  • My project is using go modules.

Describe the bug

Parent flags marked as non-persistent (Local=true) are still recognized when specified after a subcommand.

To reproduce

package main

import (
	"context"
	"log"
	"os"

	"github.com/urfave/cli/v3"
)

func main() {
	cmd := &cli.Command{
		Name:    "testprog",
		Version: "1.0",
		Commands: []*cli.Command{
			{
				Name: "subcmd",
				Commands: []*cli.Command{
					{
						Name: "nested-subcmd",
						Action: func(ctx context.Context, c *cli.Command) error {
							c.Writer.Write([]byte("The nested subcommand is executed\n"))
							return nil
						},
					},
				},
				Flags: []cli.Flag{
					&cli.StringFlag{
						Name:  "subcmd-flag",
						Local: true,
						Action: func(ctx context.Context, c *cli.Command, v string) error {
							c.Writer.Write([]byte("--subcmd-flag is presented\n"))
							return nil
						},
					},
				},
				Action: func(ctx context.Context, c *cli.Command) error {
					c.Writer.Write([]byte("The subcommand is executed\n"))
					return nil
				},
			},
		},
		Flags: []cli.Flag{
			&cli.BoolFlag{
				Name:  "root-flag",
				Local: true,
				Action: func(ctx context.Context, c *cli.Command, b bool) error {
					c.Writer.Write([]byte("--root-flag is presented\n"))
					return nil
				},
			},
		},
		Action: func(ctx context.Context, c *cli.Command) error {
			c.Writer.Write([]byte("The root command is executed\n"))
			return nil
		},
	}

	err := cmd.Run(context.Background(), os.Args)
	if err != nil {
		log.Fatal(err)
	}
}

Observed behavior

$ testprog subcmd --root-flag
--root-flag is presented
The subcommand is executed

Expected behavior

The command should produce an error, indicating that the parent flag is invalid in the subcommand context.

$ testprog subcmd --root-flag
Incorrect Usage: flag provided but not defined: -root-flag

2025/10/13 12:00:33 flag provided but not defined: -root-flag

Run go version and paste its output here

go version go1.25.0 linux/amd64

Run go env and paste its output here

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/follie/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/follie/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build580634775=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/follie/orara/go.mod'
GOMODCACHE='/home/follie/.local/share/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/follie/.local/share/go'
GOPRIVATE=''
GOPROXY='direct'
GOROOT='/nix/store/3fd683jfggglpshxprz9mi5sz8wd3c9p-go-1.25.0/share/go'
GOSUMDB='off'
GOTELEMETRY='off'
GOTELEMETRYDIR='/home/follie/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/nix/store/3fd683jfggglpshxprz9mi5sz8wd3c9p-go-1.25.0/share/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.25.0'
GOWORK=''
PKG_CONFIG='pkg-config'

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/v3relates to / is being considered for v3kind/bugdescribes or fixes a bugstatus/triagemaintainers still need to look into this

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions