Improve error message for unresolved subtype ids.
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 49e7205..1b70c41 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -72,6 +72,7 @@
   that benefit from knowing number of elements in arrays (and would otherwise
   need to buffer values to know length)
 - Added new overload for `JsonSerializer.isEmpty()`, to eventually solve #588
+- Improve error messaging (related to [jaxb-annotations#38]) to include known subtype ids.
 
 2.4.5 (not yet released)
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
index 866be42..9b9e069 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
@@ -876,15 +876,28 @@
      * Helper method for constructing exception to indicate that given
      * type id (parsed from JSON) could not be converted to a Java type.
      */
+    @Deprecated // since 2.5, use overloaded variant
     public JsonMappingException unknownTypeException(JavaType type, String id) {
         return JsonMappingException.from(_parser, "Could not resolve type id '"+id+"' into a subtype of "+type);
     }
 
+    /**
+     * @since 2.5
+     */
+    public JsonMappingException unknownTypeException(JavaType type, String id,
+            String extraDesc) {
+        String msg = "Could not resolve type id '"+id+"' into a subtype of "+type;
+        if (extraDesc != null) {
+            msg = msg + ": "+extraDesc;
+        }
+        return JsonMappingException.from(_parser, msg);
+    }
+
     public JsonMappingException endOfInputException(Class<?> instClass) {
         return JsonMappingException.from(_parser, "Unexpected end-of-input when trying to deserialize a "
                 +instClass.getName());
     }
-    
+
     /*
     /**********************************************************
     /* Overridable internal methods
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
index ea7d1bf..e35704e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
@@ -139,4 +139,9 @@
         }
         return str;
     }
+
+    @Override
+    public String getDescForKnownTypeIds() {
+        return "class name used as type id";
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
index 4a4922e..890416f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
@@ -159,7 +159,7 @@
                     // As per [JACKSON-614], use the default impl if no type id available:
                     deser = _findDefaultImplDeserializer(ctxt);
                     if (deser == null) {
-                        throw ctxt.unknownTypeException(_baseType, typeId);
+                        deser = _handleUnknownTypeId(ctxt, typeId, _idResolver, _baseType);
                     }
                 } else {
                     /* 16-Dec-2010, tatu: Since nominal type we get here has no (generic) type parameters,
@@ -243,4 +243,35 @@
         }
         return deser.deserialize(jp, ctxt);
     }
+
+    /**
+     * Helper method called when given type id can not be resolved into 
+     * concrete deserializer either directly (using given {@link  TypeIdResolver}),
+     * or using default type.
+     * Default implementation simply throws a {@link JsonMappingException} to
+     * indicate the problem; sub-classes may choose
+     *
+     * @return If it is possible to resolve type id into a {@link JsonDeserializer}
+     *   should return that deserializer; otherwise throw an exception to indicate
+     *   the problem.
+     *
+     * @since 2.5
+     */
+    protected JsonDeserializer<Object> _handleUnknownTypeId(DeserializationContext ctxt, String typeId,
+            TypeIdResolver idResolver, JavaType baseType)
+        throws IOException
+    {
+        String extraDesc;
+        if (idResolver instanceof TypeIdResolverBase) {
+            extraDesc = ((TypeIdResolverBase) idResolver).getDescForKnownTypeIds();
+            if (extraDesc == null) {
+                extraDesc = "known type ids are not statically known";
+            } else {
+                extraDesc = "known type ids = " + extraDesc;
+            }
+        } else {
+            extraDesc = null;
+        }
+        throw ctxt.unknownTypeException(_baseType, typeId, extraDesc);
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java
index 771283a..bea6d49 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeIdResolverBase.java
@@ -71,4 +71,14 @@
     public JavaType typeFromId(DatabindContext context, String id) {
         return typeFromId(id);
     }
+
+    /**
+     * Helper method used to get a simple description of all known type ids,
+     * for use in error messages.
+     *<p>
+     * TODO: demote down to be part of {@link TypeIdResolver} in 2.6 or 2.7
+     */
+    public String getDescForKnownTypeIds() {
+        return null;
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
index ddb7174..1622496 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
@@ -132,7 +132,12 @@
          */
         return _idToType.get(id);
     }    
-    
+
+    @Override
+    public String getDescForKnownTypeIds() {
+        return new TreeSet<String>(_idToType.keySet()).toString();
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java b/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java
index afb3ebf..1422ced 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestHandlerInstantiation.java
@@ -120,11 +120,12 @@
         public CustomIdResolver(String idForBean) {
             _id = idForBean;
         }
-        
+
         @Override
         public Id getMechanism() {
             return Id.CUSTOM;
         }
+
         @Override
         public String idFromValue(Object value)
         {
@@ -133,16 +134,19 @@
             }
             return "unknown";
         }
+
         @Override
         public String idFromValueAndType(Object value, Class<?> type) {
             return idFromValue(value);
         }
+
         @Override
         public void init(JavaType baseType) {
             if (initTypes != null) {
                 initTypes.add(baseType);
             }
         }
+
         @Override
         public JavaType typeFromId(DatabindContext context, String id)
         {
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
index 29f83a5..68df8f4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
@@ -2,6 +2,7 @@
 
 
 import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonTypeName;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
@@ -65,7 +66,22 @@
     static class DefaultImpl505 extends SuperTypeWithoutDefault {
         public int a;
     }
-    
+
+    @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.PROPERTY, property="type")
+    @JsonSubTypes({ @JsonSubTypes.Type(ImplX.class),
+          @JsonSubTypes.Type(ImplY.class) })
+    static abstract class BaseX { }
+
+    @JsonTypeName("x")
+    static class ImplX extends BaseX {
+        public int x;
+    }
+
+    @JsonTypeName("y")
+    static class ImplY extends BaseX {
+        public int y;
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -211,5 +227,14 @@
         assertEquals(0, ((DefaultImpl505) bean).a);
     
     }
-}
 
+    public void testErrorMessage() throws Exception {
+        ObjectMapper mapper = new ObjectMapper();
+        try {
+            mapper.readValue("{ \"type\": \"z\"}", BaseX.class);
+            fail("Should have failed");
+        } catch (JsonMappingException e) {
+            verifyException(e, "known type ids =");
+        }
+    }
+}