{"record":{"id":"a544bdffb89d9227","repo":"can1357/oh-my-pi","slug":"label-must-not-be-empty","errorCode":null,"errorMessage":"${label} must not be empty","messagePattern":"(.+?) must not be empty","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/gh-common.ts","lineNumber":39,"sourceCode":"\tconst normalized = value?.trim();\n\treturn normalized ? normalized : undefined;\n}\n\nexport function normalizePrIdentifierList(value: string | string[] | undefined): string[] {\n\tif (value === undefined) return [];\n\tconst raw = typeof value === \"string\" ? [value] : value;\n\tconst cleaned: string[] = [];\n\tfor (const entry of raw) {\n\t\tconst trimmed = entry?.trim();\n\t\tif (trimmed) cleaned.push(trimmed);\n\t}\n\treturn cleaned;\n}\n\nexport function requireNonEmpty(value: string | null | undefined, label: string): string {\n\tconst normalized = normalizeOptionalString(value);\n\tif (!normalized) {\n\t\tthrow new ToolError(`${label} must not be empty`);\n\t}\n\treturn normalized;\n}\n\nexport function appendRepoFlag(args: string[], repo: string | undefined, identifier?: string): void {\n\t// A full URL identifier already names host, repo, and number; `gh` derives\n\t// all three from it and rejects a competing `--repo`.\n\tif (!repo || identifier?.startsWith(\"https://\")) {\n\t\treturn;\n\t}\n\n\targs.push(\"--repo\", repo);\n}\n\n/** The host `gh` assumes when a ref names none and `GH_HOST` is unset. */\nexport const GITHUB_HOST = \"github.com\";\n\n/**","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/gh-common.ts#L21-L57","documentation":"requireNonEmpty validates that a GitHub-related string argument (repo, URL, ref, oid, etc.) is present after normalization; if the value is null, undefined, or whitespace-only it throws a ToolError naming the field via `label`. It guards every gh tool call from passing empty strings to the `gh` CLI.","triggerScenarios":"Calling url(), headRepository(), headRefName(), headRefOid(), resolveGitHubBranchHead(), or query() on gh-common with a missing/blank value for the field it validates — e.g. omitting repo or passing an empty string from parsed input.","commonSituations":"LLM/parsed tool arguments leave a field empty; upstream data returns null for a ref; string-trimming turns a whitespace-only value into empty.","solutions":["Supply a non-empty value for the labeled argument (e.g. pass repo as \"owner/name\").","Validate/trim user or model-provided input before calling, and prompt for the missing field when blank.","If the value is legitimately optional, branch before calling instead of passing null to a require* function."],"exampleFix":"// before\nconst branch = await headRefName(\"\");\n// after\nconst branch = branchInput?.trim() ? await headRefName(branchInput) : null;","handlingStrategy":"validation","validationCode":"function requireValue(v, label) {\n  const s = typeof v === \"string\" ? v.trim() : \"\";\n  if (!s) throw new Error(`${label} must be provided`);\n  return s;\n}\nrequireValue(repoInput, \"repo\"); // before calling the tool","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await query({ repo: repoInput });\n} catch (err) {\n  if (err instanceof ToolError && err.message.endsWith(\"must not be empty\")) {\n    // re-prompt for the missing argument\n  } else throw err;\n}","preventionTips":["Trim and check all GitHub tool string args before calling.","Treat require* functions as contracts: never pass possibly-null values into them.","Validate LLM/model-supplied arguments against a schema (required, minLength 1) before dispatch."],"tags":["validation","github","arguments"],"backgroundTag":"required-parameter-empty","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}