SnipSnap crash with FileSnipStorage and bad metadata.properties

This article describes SnipSnap 1.0b1-uttoxeter using FileSnipStorage.

SnipSnap, the software that originally ran this site, is great. I heart SnipSnap.

Unfortunately, nothing’s perfect, even SnipSnap. It occasionally crashes, and if you’re using filesystem snip storage, it may corrupt itself. (This has been discussed elsewhere.) When that happens, it will refuse to start:

SnipSnap 1.0b1-uttoxeter
Copyright (c) 2000-2004 Fraunhofer Gesellschaft
Fraunhofer Institute for Computer Architecture and Software Technology
All Rights Reserved. See License Agreement for terms and conditions of use.
Responsible Authors: Stephan J. Schmidt, Matthias L. Jugel.
>> Applications: /<path...>/applications
>> Loading: / WARNING: unable to load application 'snarfed.org': null
0 applications loaded and running (1 errors).

The server.log file will report this stacktrace:

java.lang.NullPointerException
    at org.snipsnap.snip.storage.FileSnipStorage.parseSnip(FileSnipStorage.java:298)
    at org.snipsnap.snip.storage.FileSnipStorage.traverseFileStore(FileSnipStorage.java:332)
    at org.snipsnap.snip.storage.FileSnipStorage.traverseFileStore(FileSnipStorage.java:341)
    at org.snipsnap.snip.storage.FileSnipStorage.storageAll(FileSnipStorage.java:325)
    at org.snipsnap.snip.storage.MemorySnipStorage.<init>(MemorySnipStorage.java:87)
    at org.snipsnap.snip.SnipSpaceImpl.<init>(SnipSpaceImpl.java:103)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
    at org.picocontainer.defaults.InstantiatingComponentAdapter.instantiateComponent(InstantiatingComponentAdapter.java:86)
    at org.picocontainer.defaults.InstantiatingComponentAdapter.getComponentInstance(InstantiatingComponentAdapter.java:36)
    at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:44)
    at org.picocontainer.extras.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:39)
    at org.nanocontainer.nanning.NanningComponentAdapterFactory$WeavingAdapter.getComponentInstance(NanningComponentAdapterFactory.java:81)
    at org.picocontainer.defaults.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:201)
    at org.snipsnap.container.Components.getComponent(Components.java:149)
    at org.snipsnap.net.filter.InitFilter.loadApplicationContexts(InitFilter.java:169)
    at org.snipsnap.net.filter.InitFilter.init(InitFilter.java:150)

If you see this, SnipSnap was in the middle of writing a metadata.properties file to disk when it crashed (or was killed).

Each snip has a metadata.properties file. It stores metadata for that snip, including when it was created, who created it, when it was last modified, and which files are attached to it.

Every metadata.properties file is 18 lines long. The first two lines are comments, and the next 16 are property values. Here’s an example:

#Properties for start
#Sat Dec 11 19:45:10 PST 2002
snipLinks=abcd:1
name=start
oUser=ryan
cUser=ryan
mTime=1072028160413
backLinks=http://foo.com/:2
mUser=ryan
attachments=<attachments><attachments/></attachments>
commentSnip=
labels=
version=1
permissions=Edit:Editor
application=000000001234-0000000ABCDEF-...
parentSnip=
viewCount=519
cTime=1072028160413

Since SnipSnap shut down unexpectedly, the metadata.properties file it was writing to disk was most likely truncated to zero bytes. It’s also possible, though less likely, that it was partially written to disk. Either way, when SnipSnap starts up and tries to read that file, it won’t have all of the metadata it needs, so it can’t continue.

(Note that content.txt files, which contain the actual contents of a snip, may also be truncated or partially written to disk because of a crash. SnipSnap doesn’t parse them, though, so they won’t cause this stacktrace.)

On *nix, use this command to find broken metadata.properties files:

\# run this in your snipsnap application's directory

find WEB-INF/ . -name metadata.properties -print0 | \
  xargs -0 -n1 wc -l | \
  egrep -v '^ *18'

For each file listed, simply restore it from its backup, metadata.properties.bck. SnipSnap should then restart happily. As a last resort, if the backup is corrupted too, you can use ../metadata.properties.template, which should always be ok.

P.S. Thanks to Ryan Stephenson for his related article Downtime is my favorite time.

Leave a Reply

Your email address will not be published. Required fields are marked *