abhigyanpatwari/GitNexus · error · Error
links[${i}].contract is required
Error message
links[${i}].contract is required What it means
Thrown during links[] validation when a link's 'contract' field is undefined, null, or trims to an empty string. The contract field carries the contract identifier (e.g. an HTTP route like 'GET /v1/users', a grpc method fully-qualified name, a topic name). It is required because a link without a contract binds no actual consumer-provider relationship.
Source
Thrown at gitnexus/src/core/group/config-parser.ts:87
throw new Error(`links[${i}].from "${link.from}" does not match any repo path in group`);
}
if (!link.to || !repoPaths.has(link.to as string)) {
throw new Error(`links[${i}].to "${link.to}" does not match any repo path in group`);
}
if (!VALID_CONTRACT_TYPES.includes(link.type as ContractType)) {
throw new Error(
`links[${i}].type "${link.type}" is invalid. Expected: ${VALID_CONTRACT_TYPES.join(', ')}`,
);
}
if (!VALID_ROLES.includes(link.role as ContractRole)) {
throw new Error(`links[${i}].role "${link.role}" is invalid. Expected: provider | consumer`);
}
if (
link.contract === undefined ||
link.contract === null ||
String(link.contract).trim() === ''
) {
throw new Error(`links[${i}].contract is required`);
}
return {
from: link.from as string,
to: link.to as string,
type: link.type as ContractType,
contract: String(link.contract),
role: link.role as ContractRole,
};
});
const detect = { ...DEFAULT_DETECT, ...((raw.detect as object) || {}) };
const matching = { ...DEFAULT_MATCHING, ...((raw.matching as object) || {}) };
const packages = (raw.packages as Record<string, Record<string, string>>) || {};
return {
version: 1,
name: raw.name as string,
description: (raw.description as string) || '',View on GitHub (pinned to d540b00184)
Solutions
- Set link.contract to a non-empty string describing the actual contract: an HTTP route (e.g. 'GET /v1/users'), a grpc method (e.g. 'pkg.Svc/Method'), a topic name, or a library/include identifier.
- If the contract isn't known yet, remove the entire link entry — partial links are not allowed.
Example fix
# before — empty placeholder contract
links:
- { from: services/api, to: services/worker, type: http, contract: '', role: provider }
# after
links:
- { from: services/api, to: services/worker, type: http, contract: 'GET /v1/users', role: provider } Defensive patterns
Strategy: validation
Validate before calling
function hasNonEmptyContract(link: Record<string, unknown>): boolean {
return link.contract !== undefined && link.contract !== null &&
typeof link.contract === 'string' && link.contract.trim().length > 0;
} Type guard
function linkHasContract(link: unknown): link is { contract: string } {
return typeof (link as Record<string, unknown>)?.contract === 'string' &&
((link as Record<string, unknown>).contract as string).trim().length > 0;
} Prevention
- Fill the contract field with the real route/method/topic — never leave a TODO or empty string.
- If a link's contract isn't known, omit the whole link until it is.
- Lint group.yaml to reject links whose contract trims to empty.
When it happens
Trigger: A link missing the 'contract' key; contract: null; contract: '' or contract: ' ' (whitespace-only).
Common situations: Hand-authored link left with a placeholder empty contract; the contract field accidentally deleted during edit; a template with contract: TODO that was never filled in.
Related errors
- links[${i}].from "${link.from}" does not match any repo path
- links[${i}].to "${link.to}" does not match any repo path in
- links[${i}].type "${link.type}" is invalid. Expected: ${VALI
- links[${i}].role "${link.role}" is invalid. Expected: provid
- Invalid YAML: expected an object
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/c193a177a6557bd0.
Report an issue: GitHub.