Index: modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (revision 1746) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (working copy) @@ -1520,6 +1520,11 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node public final JcrVersionNode getBaseVersion() throws RepositoryException { checkVersionable(); + // This can happen if the versionable type was added to the node, but it hasn't been saved yet + if (!hasProperty(JcrLexicon.BASE_VERSION)) { + throw new UnsupportedRepositoryOperationException(JcrI18n.requiresVersionable.text()); + } + return (JcrVersionNode)session().getNodeByUUID(getProperty(JcrLexicon.BASE_VERSION).getString()); } Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionManager.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionManager.java (revision 1746) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionManager.java (working copy) @@ -422,6 +422,14 @@ final class JcrVersionManager { throw new LockException(JcrI18n.lockTokenNotHeld.text(node.getPath())); } + /* + * This happens when we've added mix:versionable, but not saved it to create the base + * version (and the rest of the version storage graph). See MODE-704. + */ + if (!node.hasProperty(JcrLexicon.BASE_VERSION)) { + return; + } + PropertyFactory propFactory = propertyFactory(); PropertyInfo mvProp = node.nodeInfo().getProperty(ModeShapeIntLexicon.MULTI_VALUED_PROPERTIES); Index: modeshape-jcr/src/test/java/org/modeshape/jcr/ModeShapeTckTest.java =================================================================== --- modeshape-jcr/src/test/java/org/modeshape/jcr/ModeShapeTckTest.java (revision 1746) +++ modeshape-jcr/src/test/java/org/modeshape/jcr/ModeShapeTckTest.java (working copy) @@ -762,4 +762,24 @@ public class ModeShapeTckTest extends AbstractJCRTest { assertThat(fileNode.hasNode(contentNode.getName()), is(true)); assertThat(root.hasNode(pathToNode), is(false)); } + + public void testShouldReturnSilentlyWhenCheckingOutACheckedOutNode() throws Exception { + // q.v., MODE-704 + session = helper.getReadWriteSession(); + + Node root = session.getRootNode(); + + Node testNode = root.addNode("checkedOutNodeTest", "nt:unstructured"); + session.save(); + + // Add the mixin, but don't save it + testNode.addMixin("mix:versionable"); + testNode.checkout(); + + testNode.save(); + + // Now check that it still returns silently on a saved node that was never checked in. + testNode.checkout(); + + } }