pentaho/pentaho-kettle · error · KettleException
Could not locate perspective by class:
Error message
Could not locate perspective by class:
What it means
SpoonPerspectiveManager.activatePerspective(Class<? extends SpoonPerspective>) looks up the requested perspective in its registry map and throws KettleException if no perspective is registered under that class. It means the code asked to switch to a perspective that was never installed/registered with the manager.
Solutions
- Confirm the perspective is registered: call addPerspective(perspective) (or ship the perspective plugin correctly) before activation
- Check the perspective plugin's annotation/plugin metadata so it loads at Spoon startup
- Guard activation with getPerspective(clazz) != null before calling activatePerspective
- Ensure you pass the exact registered class, not a subclass or same-named class from another classloader
Example fix
// before
manager.activatePerspective(MyPerspective.class); // throws if not registered
// after
if ( manager.getPerspective(MyPerspective.class) != null ) {
manager.activatePerspective(MyPerspective.class);
} Defensive patterns
Strategy: try-catch
Validate before calling
SpoonPerspective sp = manager.getPerspective(MyPerspective.class);
if (sp == null) {
// perspective not registered — register it or skip activation
return;
} Type guard
boolean isRegistered(SpoonPerspectiveManager m, Class<? extends SpoonPerspective> c) {
return m.getPerspective(c) != null;
} Try / catch
try {
manager.activatePerspective(MyPerspective.class);
} catch (KettleException e) {
log.error("Perspective not registered: " + e.getMessage());
// stay on current perspective or register lazily then retry
} Prevention
- Register every perspective via addPerspective before any activation call
- Verify perspective plugin metadata so it loads at Spoon startup
- Call activation only after the manager is fully initialized
- Use the exact registered class (mind plugin classloaders)
When it happens
Trigger: Calling activatePerspective(SomePerspective.class) where the perspective instance was never added via addPerspective, the perspective plugin failed to load, or the class differs from the registered one (different classloader or subclass).
Common situations: A perspective plugin's plugin.xml/class is missing so it never registers; calling activatePerspective during startup before initialize() registered the perspectives; duplicate class instances across classloaders in an OSGi-ish plugin environment.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Spoon.RipDB.Exception.ErrorGettingSQLFromTransformation
- Spoon.RipDB.Exception.UnableToSaveTransformationToRepository
- There is no target to do a field mapping against!
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/d6cf8eb0a7e8cee4.
Report an issue: GitHub.
Appendix: source
Thrown at ui/src/main/java/org/pentaho/di/ui/spoon/SpoonPerspectiveManager.java:302
/**
* Activates the given instance of the class literal passed in. Activating a perspective first deactivates the current
* perspective removing any overlays its applied to the UI. It then switches the main deck to display the perspective
* UI and applies the optional overlays to the main Spoon XUL container.
*
* @param clazz
* SpoonPerspective class literal
* @throws KettleException
* throws a KettleException if no perspective is found for the given parameter
*/
public void activatePerspective( Class<? extends SpoonPerspective> clazz ) throws KettleException {
if ( this.forcePerspective ) {
// we are currently prevented from switching perspectives
return;
}
SpoonPerspective sp = perspectives.get( clazz );
if ( sp == null ) {
throw new KettleException( "Could not locate perspective by class: " + clazz );
}
PerspectiveManager perspectiveManager = getPerspectiveManagerMap().get( sp );
if ( perspectiveManager != null ) {
perspectiveManager.initializeIfNeeded();
}
unloadPerspective( activePerspective );
activePerspective = sp;
List<XulOverlay> overlays = sp.getOverlays();
if ( overlays != null ) {
for ( XulOverlay overlay : overlays ) {
try {
ResourceBundle res = null;
if ( overlay.getResourceBundleUri() != null ) {
try {
res = GlobalMessageUtil.getBundle( overlay.getResourceBundleUri(), SpoonPerspectiveManager.class );
} catch ( MissingResourceException ignored ) {
// Ignore errorsView on GitHub (pinned to f3058517a1)