plandex-ai/plandex · error

'%s' is a local-only built-in model, so it can't be used on

Error message

'%s' is a local-only built-in model, so it can't be used on Plandex Cloud

What it means

A 422 validation error thrown when running on Plandex Cloud (IS_CLOUD set) and a custom model pack references a built-in base model for which bm.IsLocalOnly() is true. Local-only built-in models depend on locally running inference and are banned from cloud model pack configurations.

Source

Thrown at app/server/handlers/models.go:248

		// ensure that all models are either built-in, being imported, or already exist
		allModelIds := modelPack.AllModelIds()

		for _, modelId := range allModelIds {
			_, exists := existingCustomModelIds[modelId]
			_, creating := inputModelIds[string(modelId)]
			bm, builtIn := shared.BuiltInBaseModelsById[modelId]

			if !exists && !creating && !builtIn {
				msg := fmt.Sprintf("'%s' is not built-in, not being imported, and not an existing custom model", modelId)
				log.Println(msg)
				http.Error(w, msg, http.StatusUnprocessableEntity)
				return
			}

			if builtIn && os.Getenv("IS_CLOUD") != "" && bm.IsLocalOnly() {
				msg := fmt.Sprintf("'%s' is a local-only built-in model, so it can't be used on Plandex Cloud", modelId)
				log.Println(msg)
				http.Error(w, msg, http.StatusUnprocessableEntity)
				return
			}
		}

		mp := modelPack.ToModelPack()
		dbMp := db.ModelPackFromApi(&mp)
		dbMp.OrgId = auth.OrgId
		dbMp.Id = mp.Id

		toUpsertModelPacks = append(toUpsertModelPacks, dbMp)
	}

	toDeleteCustomModelIds := []string{}
	toDeleteCustomProviderIds := []string{}
	toDeleteModelPackIds := []string{}

	for _, model := range customModels {
		if _, exists := inputModelIds[string(model.ModelId)]; !exists {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Replace local-only built-in model ids in the pack with cloud-compatible built-ins
  2. Remove those model entries from the pack before importing on cloud
  3. Use self-hosted Plandex if local-only models are required in packs
  4. Maintain environment-specific pack definitions

Example fix

// before (on Plandex Cloud)
{"name": "my-pack", "summarizer": {"modelId": "ollama-local-model"}}
// after (on Plandex Cloud)
{"name": "my-pack", "summarizer": {"modelId": "claude-3-haiku"}}
Defensive patterns

Strategy: validation

Validate before calling

// pre-check local-only built-ins in packs when on cloud
if isCloud {
    for _, pack := range in.CustomModelPacks {
        for _, id := range pack.AllModelIds() {
            if bm, ok := shared.BuiltInBaseModelsById[id]; ok && bm.IsLocalOnly() {
                return fmt.Errorf("pack references local-only built-in model: %q", id)
            }
        }
    }
}

Type guard

func cloudCompatibleModel(id shared.ModelId) bool {
    bm, builtIn := shared.BuiltInBaseModelsById[id]
    return !builtIn || !bm.IsLocalOnly()
}

Try / catch

// deterministic 422 — swap local-only models then resubmit once
if resp.StatusCode == 422 && strings.Contains(bodyText, "local-only built-in model") {
    input = replaceLocalOnlyModels(input)
    return upsert(input)
}

Prevention

When it happens

Trigger: POST to the upsert custom models endpoint against Plandex Cloud with a CustomModelPacks entry whose AllModelIds() includes a local-only built-in base model id (e.g. a locally hosted ollama model that ships as a built-in).

Common situations: Copying a self-hosted model pack config to cloud; shared team config files that mix local and cloud environments; forgetting that the restriction applies to any role in the pack, not just the planner.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/886a3ba4be88da73. Report an issue: GitHub.