semaphoreui/semaphore · error

deploy is build but build_template does not exist in…

Error message

deploy is build but build_template does not exist in templates[].name

What it means

Thrown by BackupTemplate.Verify when a template has Type "deploy" but its BuildTemplate reference does not resolve to a name in backup.Templates. Deploy-type templates build on another template, so the referenced build template must be present in the same backup.

Solutions

  1. Include the referenced build template in backup.Templates.
  2. Update the deploy template's buildTemplate field to an existing templates[].name.
  3. Change the template type or remove the buildTemplate reference if it should not build.
  4. Set BuildTemplate to null if the deploy template no longer builds from another template (if allowed).

Example fix

// before
"templates": [{"name": "deploy-app", "type": "deploy", "buildTemplate": "build-app"}]
// after (add the dependency)
"templates": [{"name": "build-app", "type": "build"}, {"name": "deploy-app", "type": "deploy", "buildTemplate": "build-app"}]
Defensive patterns

Strategy: validation

Validate before calling

if t.Type == "deploy" && !templateNameExists(t.BuildTemplate, backup.Templates) {
  return fmt.Errorf("deploy template %q missing build template %q", t.Name, t.BuildTemplate)
}

Type guard

func templateNameExists(name string, tmpls []BackupTemplate) bool {
  for _, t := range tmpls {
    if t.Name == name { return true }
  }
  return false
}

Try / catch

if err := tmpl.Verify(backup); err != nil {
  if strings.Contains(err.Error(), "build_template does not exist") {
    // export the build template too, then retry
  }
}

Prevention

When it happens

Trigger: Verify where string(e.Type) == "deploy" and getEntryByName[BackupTemplate](e.BuildTemplate, backup.Templates) == nil — exporting the deploy template without the build template it depends on, or a typo/renamed build template.

Common situations: Partial exports containing only deploy templates; build templates deleted after backup; renaming a build template between backup and restore; copying deploy templates across projects.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/2bca2687b274bcdb. Report an issue: GitHub.

Appendix: source

Thrown at services/project/restore.go:275

		return fmt.Errorf("vault_key does not exist in keys[].name")
	}

	if e.Vaults != nil {
		for _, vault := range e.Vaults {
			if vault.VaultKey != nil {
				if getEntryByName[BackupAccessKey](vault.VaultKey, backup.Keys) == nil {
					return fmt.Errorf("vaults[].vaultKey does not exist in keys[].name")
				}
			}
		}
	}

	if e.View != nil && getEntryByName[BackupView](e.View, backup.Views) == nil {
		return fmt.Errorf("view does not exist in views[].name")
	}

	if buildTemplate := getEntryByName[BackupTemplate](e.BuildTemplate, backup.Templates); string(e.Type) == "deploy" && buildTemplate == nil {
		return fmt.Errorf("deploy is build but build_template does not exist in templates[].name")
	}

	return nil
}

func (e BackupTemplate) Restore(b *BackupDB) error {
	var InventoryID *int
	if e.Inventory != nil {
		if k := findEntityByName[db.Inventory](e.Inventory, b.inventories); k == nil {
			return fmt.Errorf("inventory does not exist in inventories[].name")
		} else {
			id := k.GetID()
			InventoryID = &id
		}
	}

	var EnvironmentIDs []int
	for i := range e.Environments {

View on GitHub (pinned to 1774ccb71a)