kalup

Errors and warnings

Every E_ and W_ code Kalup can print, what it means, its exit code and how to fix it

Every problem Kalup reports is an issue with a code. E_ codes are errors: the command stopped or found something invalid. W_ codes are warnings: the command finished and the exit code stays 0.

Each code has its own section on this page, with a stable anchor you can link to: /docs/reference/errors#e_not_data. An issue in the output also names the matching page in the installed package, for example (docs: errors/E_NOT_DATA.md). It is the same content.

In --json mode every issue has code, message, and often file, line, configPath, fix and humanRequired. JSON output describes the fields, and Exit codes the numbers.

Agents: act on fix, not on the message. On exit 3, fix the file and line the issue names, then validate again. On exit 4 or humanRequired: true, stop and hand the issue to the user.

Index

CodeExitMeaning
E_AUTH1HubSpot rejected the key (401)
E_BAD_CHAIN3A chain call after a builder that Kalup does not accept
E_BIOME_CONFIG1init found a biome.json that is not valid JSON
E_CONFIG_EXISTS1init found an existing kalup.config.ts
E_DAILY_LIMIT1The portal used its daily API limit
E_DUPLICATE_ADDRESS3One address defined twice
E_DUPLICATE_KEY3A name used twice where it must be unique
E_FIRST_PULLthe pull'sinit wrote the files but the first pull failed
E_HS_PREFIX3A managed property named with HubSpot's hs_ prefix
E_HTTP1Any other HubSpot error
E_IR_SCHEMA3The derived IR does not match the ir/1 schema
E_KEY_COLLISION3Two properties of one object share a key
E_LIFECYCLE3A lifecycle block contradicts itself
E_MISSING_EXPORT3A file under kalup/ defines no object
E_MISSING_KEY1The variable for the read key is not set
E_NOT_DATA3Something outside the config grammar
E_NOT_IMPLEMENTED1A command this version does not have yet
E_NO_CONFIG1No kalup.config.ts found
E_OVERRIDE_AMBIGUOUS1A name override matches two portal resources
E_PORTAL_ID3A target's portalId is missing or invalid
E_RATE_LIMIT1HubSpot kept answering 429 after three retries
E_REFERENCE_DEFINITION3A property is neither managed nor a valid reference
E_SCOPE0 or 1The key lacks a scope (403)
E_TARGET_NAME3A target is named config
E_TARGET_PORTAL_MISMATCH4The key belongs to another portal
E_TYPE_FIELDTYPE3A fieldType the builder does not allow
E_UNEXPECTED1An error Kalup has no code for
E_UNKNOWN_BUILDER3p.<kind> is not a builder
E_UNKNOWN_GROUP3A property's group is not declared
E_UNKNOWN_INCLUDE3include names properties the portal does not have
E_UNKNOWN_OBJECT3An object the portal does not have
E_UNKNOWN_OVERRIDE3An override key that is not an address in config
E_UNKNOWN_TARGET3--target names an undeclared target
E_UNREACHABLE1status got no answer from HubSpot
E_UNSUPPORTED_FILE3A file under kalup/ this version does not read
E_USAGE1The command line is wrong
E_WRITE_IN_READ_MODE1A request to a write path was refused
W_CODEC_MISMATCH0The file's builder does not match the portal type
W_JSON_FIELDTYPE0A p.json property that is not a textarea
W_KEY_COLLISION0A new property's default key was taken
W_LARGE_SCOPE0The first pull wrote more than 200 properties for an object
W_PIN_EXPIRES0A pinned HubSpot API version expires within 90 days
W_PREFIX0A managed property lacks the project prefix
W_RATE_HEADERS0No rate-limit headers (from status)
W_RATE_LIMIT0No rate-limit headers (from pull)
W_UNRESOLVED0A resource carries an $unresolved marker
W_UNSUPPORTED_TYPE0A portal property no builder can carry was skipped

Errors

E_AUTH

HubSpot rejected the read key with a 401. Exit 1. Raised by init, pull and status.

The key is wrong, revoked or expired. status reports it for that target and goes on to check the others.

Fix. Check the key in the variable the target reads: credentials.read.env, or HUBSPOT_SERVICE_KEY when the target names none. If it was revoked, a person creates a new one in HubSpot. When the request needed a scope, the fix names it.

E_AUTH: HubSpot rejected the key (401). (fix: Check that the key is valid and not expired. It needs the scope crm.schemas.companies.read.)

E_BAD_CHAIN

A builder call is followed by a chain call Kalup does not accept. Exit 3. Raised by every command that reads config.

After p.<kind>(...) only .required(), .readonly() and .managed(false) are allowed, each once. .optional(), .managed(true), .required without parentheses and .required() twice are all this error.

Fix. Use one of the three calls, once each. A property is nullable unless it has .required(), so there is no .optional().

seatCount: p.number('seat_count').optional(),
kalup/objects/companies.ts:5: E_BAD_CHAIN: .optional() is not a chain call (fix: use .required(), .readonly() or .managed(false))

E_BIOME_CONFIG

init found a biome.json that is not valid JSON. Exit 1. Nothing was written.

init adds !kalup/** to files.includes in biome.json, so it reads that file before it writes anything. Comments are stripped first. A biome.jsonc that does not parse is not an error: init leaves it alone and prints a note.

Fix. Fix the JSON in biome.json (a trailing comma is the usual cause), then run npx kalup init --portal <id> again.

biome.json: E_BIOME_CONFIG: biome.json is not valid JSON: <parser message> (fix: fix the file, then run npx kalup init again)

E_CONFIG_EXISTS

init refused to run because kalup.config.ts already exists. Exit 1. Nothing was written.

init runs once per project and never overwrites a config.

Fix. To refresh the files from the portal, run npx kalup pull --target <name>. To start over, remove kalup.config.ts first.

kalup.config.ts: E_CONFIG_EXISTS: kalup.config.ts already exists in /work/acme-crm (fix: this is a kalup project already: run npx kalup pull --target <name>, or remove the file to start over)

E_DAILY_LIMIT

The portal has used its daily HubSpot API limit. Exit 1. Raised by init, pull and status.

HubSpot answered 429 with the DAILY policy. Kalup does not retry it. Every app on the portal shares the same daily limit.

Fix. Run the command again after the time in the fix, which is the next midnight in the portal's time zone.

E_DAILY_LIMIT: The portal has used its daily API limit. (fix: Try again after 2026-09-23T22:00:00.000Z.)

E_DUPLICATE_ADDRESS

One address is defined twice, in two files or in two exports. Exit 3.

Every group, property and custom object has one address, such as group:companies/billing. Two exports of companies that both declare the group billing, or the same property in two files, give that address twice. The issue names both places.

Fix. Keep one definition and remove the other, or give one of them another internal name.

kalup/objects/companies.ts:15: E_DUPLICATE_ADDRESS: group:companies/billing is defined twice: kalup/objects/companies.ts:5 and kalup/objects/companies.ts:15 (fix: remove or rename one of the two definitions)

E_DUPLICATE_KEY

A name is used twice where it must be unique. Exit 3.

The same key twice in one object literal, the same export name twice in one file, or one internal name under two keys of one export.

Fix. Remove one of the two entries, or rename it.

properties: {
  seatCount: p.number('seat_count'),
  seatTotal: p.number('seat_count'),
},
kalup/objects/companies.ts:9: E_DUPLICATE_KEY: internal name 'seat_count' is used by two keys of Company: 'seatCount' and 'seatTotal' (fix: remove or rename one of the two entries)

E_FIRST_PULL

init wrote the project files, but the first pull failed. The exit code is the pull's.

init checks the portal, writes kalup.config.ts, .gitignore, AGENTS.md, CLAUDE.md and, when it finds a formatter, its ignore entry, then runs a pull. The issue before this one says why the pull failed.

Fix. Fix that issue, then run the pull yourself. Do not run init again: the config exists now, so it would stop with E_CONFIG_EXISTS.

E_AUTH: HubSpot rejected the key (401). (fix: Check that the key is valid and not expired. It needs the scope crm.schemas.companies.read.)
E_FIRST_PULL: The project files are written, but the first pull failed. (fix: fix the issue above, then run npx kalup pull --target sandbox)

E_HS_PREFIX

A managed property's internal name starts with hs_. Exit 3.

HubSpot uses hs_ for its own properties, and Kalup never claims that prefix for a property it would own. Whether HubSpot refuses such a create is not confirmed. A reference, a property with no definition, may carry the prefix.

Fix. Give the property another internal name, or drop label, group and fieldType so it refers to HubSpot's property.

seatCount: p.number('hs_seat_count', { label: 'Seat count', group: 'billing', fieldType: 'number' }),
kalup/objects/companies.ts:9: E_HS_PREFIX: 'hs_seat_count' starts with hs_, the prefix HubSpot uses for its own properties (fix: rename the property, or drop label, group and fieldType to reference it)

E_HTTP

HubSpot returned an error Kalup has no other code for. Exit 1.

A 400, a 404, a 5xx that three retries did not clear, or a success whose body is not JSON (often a proxy's HTML page). The issue holds the status, the method, the path and HubSpot's message when it sent one.

Fix. A 5xx is usually temporary: run the command again later. A 404 on a properties list means the object does not exist in that portal. A body that is not JSON points at a proxy between you and HubSpot.

E_HTTP: HubSpot returned 503 for GET /crm/properties/2026-09/companies.

E_IR_SCHEMA

The IR that kalup ir derived does not match the ir/1 JSON Schema. Exit 3.

kalup ir and kalup ir --check check the IR against the schema. Here configPath is a path in the IR, such as targets.sandbox.portalId, not a place in a file. From config files it comes together with a validate issue that explains it.

Fix. Fix the other issues first; this one goes with them. If it is the only issue left, it is a bug in Kalup: report it with the issue text.

kalup.config.ts:9: E_PORTAL_ID: portalId 0 is not a positive integer (fix: set portalId to the portal ID shown in HubSpot, a positive integer)
E_IR_SCHEMA: expected at least 1

E_KEY_COLLISION

Two properties of one object have the same key. Exit 3.

The app reads every property of an object through one type, so keys must differ. Within one export a repeated key is E_DUPLICATE_KEY; this code is for two exports of the same object.

Fix. Rename one of the keys. The internal name stays, so nothing changes in HubSpot.

export const Company = defineObject('companies', { properties: { owner: p.string('acme_owner') } })
export const CompanyExtra = defineObject('companies', { properties: { owner: p.string('acme_owner_name') } })
kalup/objects/companies.ts:39: E_KEY_COLLISION: key 'owner' is used by two properties of companies: property:companies/acme_owner and property:companies/acme_owner_name (fix: rename one of the two keys)

E_LIFECYCLE

A lifecycle block contradicts itself. Exit 3.

removedOptions names a value that is still in options, or ignoreChanges names something other than label, group, fieldType, description, options, hasUniqueValue or formField.

Fix. Take the value out of options or out of removedOptions. Spell ignoreChanges entries as definition field names.

options: [{ value: 'trial', label: 'Trial' }, { value: 'active', label: 'Active' }],
lifecycle: { removedOptions: ['trial'], ignoreChanges: ['colour'] },
kalup/objects/companies.ts:14: E_LIFECYCLE: removedOptions names 'trial', which is still in options (fix: remove it from options or from removedOptions)
kalup/objects/companies.ts:14: E_LIFECYCLE: ignoreChanges names 'colour', which is not a definition field (fix: use one of label, group, fieldType, description, options, hasUniqueValue, formField)

E_MISSING_EXPORT

A file under kalup/ has no defineObject or defineCustomObject export. Exit 3.

Kalup reads every .ts file under kalup/ except kalup/index.ts as an object file. A file with only imports, or an empty file, has nothing to read.

Fix. Add the export, or move the file out of kalup/.

kalup/objects/empty.ts:1: E_MISSING_EXPORT: no defineObject or defineCustomObject export in this file (fix: add `export const <Name> = defineObject('<object>', {...})`)

E_MISSING_KEY

The variable that should hold the read key is not set. Exit 1. Raised by init, pull and status.

The variable is the target's credentials.read.env, or HUBSPOT_SERVICE_KEY when the target has no credentials. init always reads HUBSPOT_SERVICE_KEY. Kalup looks in the process environment, then in .env in the project directory. status reports it per target and checks the others.

Fix. A person sets the variable in the shell or adds NAME=value to .env. Never paste the key into a chat, a log or a commit. .env belongs in .gitignore.

E_MISSING_KEY: HUBSPOT_SANDBOX_KEY is not set. (fix: Set HUBSPOT_SANDBOX_KEY in the environment or in .env in the project directory.)

E_NOT_DATA

A config file holds something outside the grammar Kalup reads. Exit 3.

Kalup parses config as data and never runs it. Identifiers, spreads, template strings, calls other than the builders, a comment that is not on its own line above an entry, an unknown field, a value of the wrong type, and a missing required field are all this code. Required fields include a custom object's labels and primaryDisplayProperty, a group's label, an option's value and label, and credentials.read. The message and the fix say which one. Config files lists the grammar.

Fix. Follow the fix. To keep a note, put a // comment on its own line above the property, group or export.

seatCount: p.number('seat_count'), // counted by hand
kalup/objects/companies.ts:5: E_NOT_DATA: this comment is not attached to an entry (fix: move this comment above the entry it describes)

E_NOT_IMPLEMENTED

The command is planned but not in this version. Exit 1.

kalup --help marks these commands (not implemented yet): compare, plan, snapshot, docs and apply.

Fix. Use the commands this version has: init, pull, validate, ir, fmt and status.

E_NOT_IMPLEMENTED: kalup plan is not implemented yet

E_NO_CONFIG

No kalup.config.ts in the working directory or any directory above it. Exit 1.

Every command except init starts by looking for kalup.config.ts, from the working directory upwards.

Fix. Run the command inside the project. For a new project, run npx kalup init --portal <id>.

E_NO_CONFIG: no kalup.config.ts in /work/notes or any directory above it (fix: run npx kalup init --portal <id> in the project directory)

E_OVERRIDE_AMBIGUOUS

A name override is ambiguous because the portal holds both names. Exit 1. Raised by pull.

overrides: { '<address>': { name: '<portal name>' } } says the resource has another name in this portal. When the portal also holds a resource under the address's own name, pull cannot tell which one the address means.

Fix. Remove the override if the address's own name is the right one, or rename one of the two in HubSpot.

overrides: { 'property:subscription/renewal_date': { name: 'renewaldate' } },
E_OVERRIDE_AMBIGUOUS: the portal holds both 'renewaldate' and 'renewal_date' on subscription, so the name override for property:subscription/renewal_date is ambiguous (fix: remove the override, or rename one of the two in HubSpot)

E_PORTAL_ID

A target has no portalId, or it is not a positive integer. Exit 3.

portalId pins the target to one portal. Every networked command checks the key against it.

Fix. Set portalId to the Hub ID from the HubSpot account menu. Do not change a pin to make a mismatch go away; see E_TARGET_PORTAL_MISMATCH.

kalup.config.ts:10: E_PORTAL_ID: portalId 0 is not a positive integer (fix: set portalId to the portal ID shown in HubSpot, a positive integer)

E_RATE_LIMIT

HubSpot kept answering 429 after three retries. Exit 1.

Kalup honours Retry-After, else backs off, and retries three times. Other apps on the same portal share the limit.

Fix. Wait a minute and run the command again.

E_RATE_LIMIT: HubSpot rate limit hit and 3 retries did not clear it.

E_REFERENCE_DEFINITION

A property is neither managed nor a valid reference. Exit 3.

A property is one of three things: a full definition with label, group and fieldType; p.enum or p.multiEnum with options only; or no definition. A definition missing one of the three fields, options on another builder, or .managed(false) on a property with no full definition is this error.

Fix. Add the missing fields, or drop the definition to reference the portal's property.

seatTotal: p.number('seat_total', { label: 'Seat total' }),
kalup/objects/companies.ts:23: E_REFERENCE_DEFINITION: a definition needs label, group and fieldType (fix: add the missing fields, or drop the definition)

E_SCOPE

HubSpot answered 403 because the key lacks a scope. Exit 0 or 1, depending on where it happens.

  • In pull, a 403 on a properties, groups or schemas list is a gap: that object is skipped, the rest continue, and the exit code is 0.
  • In status, a 403 on a scope check marks that scope missing, and the exit code is 0.
  • A 403 on account-info stops the command with exit 1.

Fix. A person adds the scope named in the fix to the key in HubSpot. A key can only hold scopes its creator has, so a Super Admin creates it.

E_SCOPE: HubSpot refused GET /crm-object-schemas/2026-09/schemas (403). The key likely lacks the scope crm.schemas.custom.read. (fix: Add the scope crm.schemas.custom.read to the key.)

E_TARGET_NAME

A target is named config. Exit 3.

compare, when it arrives, uses the word config for the config side, so no target may take it.

Fix. Rename the target, for example to sandbox or production.

kalup.config.ts:9: E_TARGET_NAME: a target may not be named 'config': compare uses that word for the config side (fix: rename the target)

E_TARGET_PORTAL_MISMATCH

The key belongs to another portal than the one pinned. Exit 4, with humanRequired: true. Raised by init, pull and status.

These commands read account-info with the target's key before anything else; init does the same against --portal. When the key's portal differs from the pin, nothing else is sent and nothing is written.

Fix. Stop. A person checks which key is in the variable and which portal portalId names.

Agents: hand this to the user. Do not edit portalId or the key yourself. Changing the pin to match the key is how the wrong portal gets read.

E_TARGET_PORTAL_MISMATCH: The key in HUBSPOT_PROD_READ_KEY belongs to portal 3333333, not portal 2222222 pinned for target production. (fix: The key in HUBSPOT_PROD_READ_KEY belongs to portal 3333333. Ask the user to check the key and the pinned portalId for target production.)

E_TYPE_FIELDTYPE

A fieldType the builder does not allow. Exit 3.

Each builder allows some fieldType values. p.enum takes select, radio or booleancheckbox, and p.multiEnum only checkbox. Property builders has the full list.

Fix. Use one of the values in the fix, or change the builder: a checkbox enumeration is p.multiEnum.

billingStatus: p.enum('billing_status', { label: 'Billing status', group: 'billing', fieldType: 'checkbox', options: [...] }),
kalup/objects/companies.ts:14: E_TYPE_FIELDTYPE: fieldType 'checkbox' is not allowed for p.enum (type enumeration) (fix: use one of 'select', 'radio', 'booleancheckbox')

E_UNEXPECTED

An error Kalup has no code for. Exit 1.

Anything that is not a Kalup or HubSpot error: a file it cannot read, or a request that got no answer in init or pull. The message is the first line of the error, stripped of control characters. It never holds a key.

Fix. Read the message. A network failure clears when the network does. If it looks like a bug, report it with the command you ran and this line.

E_UNEXPECTED: fetch failed

E_UNKNOWN_BUILDER

p.<kind> is not a builder. Exit 3.

The builders are p.string, p.number, p.boolean, p.date, p.datetime, p.enum, p.multiEnum, p.stringArray and p.json. HubSpot field types such as text are not builders.

Fix. Pick the builder for the HubSpot type and put the field type in fieldType.

seatCount: p.text('seat_count'),
kalup/objects/companies.ts:5: E_UNKNOWN_BUILDER: p.text is not a builder (fix: use one of p.string, p.number, p.boolean, p.date, p.datetime, p.enum, p.multiEnum, p.stringArray, p.json)

E_UNKNOWN_GROUP

A property's group is not in its object's groups block. Exit 3.

A managed definition names its group by internal name, and that group must be declared under groups in the same export.

Fix. Add the group to groups, or use a group that is there. kalup pull writes every group a pulled property uses.

seatCount: p.number('seat_count', { label: 'Seat count', group: 'billing', fieldType: 'number' }),
kalup/objects/companies.ts:5: E_UNKNOWN_GROUP: group 'billing' is not in the groups of companies (fix: add billing: { label: '...' } to the groups block)

E_UNKNOWN_INCLUDE

objects.<key>.include names properties the portal does not have. Exit 3. Raised by pull. Nothing is written.

pull checks every include name against the portal's property list for that object, after reading all objects.

Fix. Remove the names, or correct them to the internal names shown in HubSpot's property settings.

kalup.config.ts:6: E_UNKNOWN_INCLUDE: objects.companies.include names properties the portal does not have: billing_colour (fix: remove them, or check the internal names in HubSpot)

E_UNKNOWN_OBJECT

A key under objects is neither a standard object nor a custom object in the portal. Exit 3. Raised by pull. Nothing is written.

A key that is not a standard object name (contacts, companies, deals, line_items and the rest, plural) is read as a custom object. pull lists the portal's custom objects and none has that name.

Fix. Use one of the names the message lists, or remove the key. Standard objects use HubSpot's plural API name: companies, not company.

kalup.config.ts:8: E_UNKNOWN_OBJECT: 'subscriptions' is not a standard object or a custom object in the portal (custom objects: subscription, renewal) (fix: use one of the names listed, or remove the key)

E_UNKNOWN_OVERRIDE

An override key is not an address in config. Exit 3.

targets.<name>.overrides is keyed by address: property:<object>/<name>, group:<object>/<name> or object:<name>. The address must exist in the config files.

Fix. Use an address that kalup ir lists, or remove the override. Add the property to config first if it is missing.

kalup.config.ts:13: E_UNKNOWN_OVERRIDE: override 'property:companies/seat_size' is not an address in config (fix: use an address that kalup ir lists, or remove the override)

E_UNKNOWN_TARGET

--target names a target that kalup.config.ts does not declare. Exit 3.

Commands check --target against the targets block before they send anything.

Fix. Use a declared name (the fix lists them), or add the target with its portalId and credentials.

kalup.config.ts:8: E_UNKNOWN_TARGET: target 'staging' is not declared (fix: use one of sandbox, production, or declare targets.staging)

E_UNREACHABLE

status got no answer from HubSpot. Exit 1.

A request failed before any response: no network, DNS, a proxy or a firewall. status marks the target unreachable and checks the others. The message is the network error.

Fix. Check the connection and any proxy, then run kalup status again.

E_UNREACHABLE: fetch failed

E_UNSUPPORTED_FILE

A file under kalup/ that this version does not read. Exit 3.

kalup/removed.ts (tombstones), anything under kalup/pipelines/, and a defineConfig file under kalup/. Kalup reports them instead of skipping them silently.

Fix. Move the file out of kalup/ until a release reads it. A defineConfig file belongs at the project root as kalup.config.ts.

kalup/pipelines/deals.ts:1: E_UNSUPPORTED_FILE: this version does not read pipelines yet (fix: move kalup/pipelines/deals.ts out of kalup/ until a release reads it)

E_USAGE

The command line is wrong. Exit 1.

An unknown command or flag, a flag without its value, an argument the command does not take, pull without --target, or init without a valid --portal, with a flag it does not take, or with --target config. Without --json the usage text follows the issue.

Fix. Run kalup --help and correct the command.

E_USAGE: kalup pull needs --target <name> (fix: run kalup --help)

E_WRITE_IN_READ_MODE

Kalup refused to send a request to a write path. Exit 1. Nothing was sent.

Every request goes through one HTTP layer that allows only paths tagged read. This version only reads, so no command should ever reach a write path. See Network and safety.

Fix. This is a bug in Kalup. Report it with the command you ran.

E_WRITE_IN_READ_MODE: POST /crm/properties/2026-09/{objectType} is a write path and this version only reads.

Warnings

A warning never changes the exit code. In human output it is printed on stderr after the command's output; with --json it is in issues next to ok: true.

W_CODEC_MISMATCH

From pull: the file's builder does not match the portal's property type.

The file has, say, p.string for a property that is a number in the portal. Pull keeps the property exactly as written and refreshes nothing on it, so the app's types do not change under it.

Fix. Change the builder to match the portal type, or keep it if the app relies on it.

W_CODEC_MISMATCH: property:companies/seat_count is p.string in the file but type number in the portal; the file keeps p.string and nothing is refreshed (fix: change the builder to match the portal type, or keep it if the app relies on it)

W_JSON_FIELDTYPE

From validate: a p.json property whose fieldType is not textarea. JSON text is often longer than one line, so it belongs in a textarea.

Fix. Set fieldType: 'textarea'.

kalup/objects/companies.ts:24: W_JSON_FIELDTYPE: p.json 'acme_plan_meta' has fieldType 'text'; JSON text belongs in a textarea (fix: set fieldType: 'textarea')

W_KEY_COLLISION

From pull: a new property's default key was taken, so its internal name is the key.

Pull keys a new property by the camelCase of its internal name. When another property of the object already has that key, the new one gets its internal name as key.

Fix. Rename either key to what the app should call it. Pull keeps keys as written from then on.

W_KEY_COLLISION: property:companies/seat_count: the key seatCount is taken, so its internal name is the key (fix: rename one of the two keys)

W_LARGE_SCOPE

From init: the first pull wrote more than 200 properties for one object.

init writes {} for each object, so every custom property is in the pull scope.

Fix. If the app needs only some of them, set custom: false for that object and list the ones it needs under include. Properties already in the file stay; pull never removes anything.

objects: {
  companies: { custom: false, include: ['seat_count', 'billing_status'] },
},
W_LARGE_SCOPE: the first pull wrote 312 properties for companies: every custom property is in the pull scope (fix: set objects.companies.custom to false and list the properties the app needs under objects.companies.include)

W_PIN_EXPIRES

From status: a HubSpot API version Kalup pins expires within 90 days.

HubSpot supports each dated API version for 18 months. Kalup pins one version per API family and warns once per family as the end nears.

Fix. Upgrade kalup to a release that pins a newer version.

W_PIN_EXPIRES: the crm.properties API pin 2026-09 expires 2028-03 (fix: upgrade kalup to a release that pins a newer version)

W_PREFIX

From validate: a managed property's internal name lacks the project prefix.

prefix in kalup.config.ts is set, and a property Kalup would own does not start with it. References are not checked.

Fix. Rename the property to carry the prefix, or clear prefix. A property already in HubSpot keeps its internal name; renaming means a new property.

kalup/objects/companies.ts:14: W_PREFIX: 'billing_status' does not carry the project prefix 'acme_' (fix: rename it to acme_billing_status, or clear prefix in kalup.config.ts)

W_RATE_HEADERS

From status: HubSpot sent no rate-limit headers. Kalup paces requests from those headers; without them it sends at most 8 requests per second. Service keys may not return the headers. pull reports the same thing as W_RATE_LIMIT.

Fix. Nothing to fix.

W_RATE_HEADERS: HubSpot sent no rate-limit headers. Sending at most 8 requests per second.

W_RATE_LIMIT

From pull: HubSpot sent no rate-limit headers, so Kalup sends at most 8 requests per second. status reports the same thing as W_RATE_HEADERS.

Fix. Nothing to fix. A large pull takes a little longer.

W_RATE_LIMIT: HubSpot sent no rate-limit headers. Sending at most 8 requests per second.

W_UNRESOLVED

From validate: a resource carries an $unresolved marker.

The marker, { $unresolved: { kind, id, from } }, stands for a portal ID that could not be mapped to an address. In this version no command writes it and the config grammar has no place for it, so it should not appear.

Fix. If you see it, report it with the command you ran. The fix names kalup bind, which a later version adds to map the ID to an address.

W_UNRESOLVED: workflow:renewal_reminder carries team ID 8841 from target production, which no address maps to (fix: run kalup bind workflow:renewal_reminder 8841 --target <target> to map it, or replace it with a $ref)

W_UNSUPPORTED_TYPE

From pull: a portal property no builder can carry was skipped.

Its HubSpot type has no builder (object_coordinates, json, or a type Kalup does not know), or it is a managed property whose fieldType its builder does not allow. A property already in the file is then kept and printed missing in portal.

Fix. Nothing to fix in config. If the app needs the value, read it outside Kalup.

W_UNSUPPORTED_TYPE: property:companies/office_location has type object_coordinates and fieldType text, which no builder carries; skipped

On this page