sipeed/picoclaw · error

workspace is not initialized

Error message

workspace is not initialized

What it means

A skills subcommand asked for the workspace path but d.workspace is empty — either cfg.WorkspacePath() returned "" for the loaded config, or PersistentPreRunE never ran to populate it. It is a defensive guard used by workspaceFn(), which install-builtin and similar subcommands depend on.

Source

Thrown at cmd/picoclaw/internal/skills/command.go:54

			d.skillsLoader = skills.NewSkillsLoader(d.workspace, globalSkillsDir, builtinSkillsDir)

			return nil
		},
		RunE: func(cmd *cobra.Command, _ []string) error {
			return cmd.Help()
		},
	}

	loaderFn := func() (*skills.SkillsLoader, error) {
		if d.skillsLoader == nil {
			return nil, fmt.Errorf("skills loader is not initialized")
		}
		return d.skillsLoader, nil
	}

	workspaceFn := func() (string, error) {
		if d.workspace == "" {
			return "", fmt.Errorf("workspace is not initialized")
		}
		return d.workspace, nil
	}

	cmd.AddCommand(
		newListCommand(loaderFn),
		newInstallCommand(),
		newInstallBuiltinCommand(workspaceFn),
		newListBuiltinCommand(),
		newRemoveCommand(),
		newSearchCommand(),
		newShowCommand(loaderFn),
	)

	return cmd
}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Run picoclaw's workspace initialization (e.g. `picoclaw init`) so the config carries a workspace path.
  2. Set the workspace explicitly in the config file picoclaw loads.
  3. If invoking programmatically, execute via the parent `skills` command so PersistentPreRunE runs, or populate deps yourself.
  4. Sanity-check with `picoclaw skills list`, which exercises the same loader path.

Example fix

# before
picoclaw skills install-builtin   # config has no workspace set
# after
picoclaw init                     # then retry
picoclaw skills install-builtin
Defensive patterns

Strategy: validation

Validate before calling

cfg, err := internal.LoadConfig()
if err != nil {
    return err
}
if cfg.WorkspacePath() == "" {
    return fmt.Errorf("workspace is not configured — run `picoclaw init` first")
}

Type guard

func hasWorkspace(cfg *internal.Config) bool {
    return cfg.WorkspacePath() != ""
}

Prevention

When it happens

Trigger: Invoking `picoclaw skills install-builtin` (the subcommand wired to workspaceFn at command.go:62) when the loaded config yields an empty WorkspacePath, or embedding the cobra command in a way that skips PersistentPreRunE (command.go:54).

Common situations: Fresh install where workspace initialization was never completed, a config.json copied without the workspace setting, or programmatic invocation (cmd.Execute on a subcommand directly) that bypasses the parent's PersistentPreRunE.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/ff7584dc363f42a6. Report an issue: GitHub.