Sounds like you are looking for
The former is for doing cleanup unconditionally. The latter is for handling errors - in general or of specific types.
unwind-protect is a special form in `C source code'.
(unwind-protect BODYFORM UNWINDFORMS...)
Do BODYFORM, protecting with UNWINDFORMS.
If BODYFORM completes normally, its value is returned
after executing the UNWINDFORMS.
If BODYFORM exits nonlocally, the UNWINDFORMS are executed anyway.
See the Elisp manual, node Cleanups.
condition-case is a special form in `C source code'.
(condition-case VAR BODYFORM &rest HANDLERS)
Regain control when an error is signaled.
Executes BODYFORM and returns its value if no error happens.
Each element of HANDLERS looks like (CONDITION-NAME BODY...)
where the BODY is made of Lisp expressions.
A handler is applicable to an error
if CONDITION-NAME is one of the error's condition names.
If an error happens, the first applicable handler is run.
The car of a handler may be a list of condition names instead of a
single condition name; then it handles all of them. If the special
condition name `debug' is present in this list, it allows another
condition in the list to run the debugger if `debug-on-error' and the
other usual mechanisms says it should (otherwise, `condition-case'
suppresses the debugger).
When a handler handles an error, control returns to the `condition-case'
and it executes the handler's BODY...
with VAR bound to (ERROR-SYMBOL . SIGNAL-DATA) from the error.
(If VAR is nil, the handler can't access that information.)
Then the value of the last BODY form is returned from the `condition-case'
See also the function `signal' for more info.
See the Elisp manual, node Handling Errors.